发布网友 发布时间:2024-09-29 04:51
共1个回答
热心网友 时间:2024-11-17 10:07
导读:很多朋友问到关于python多线程能开多少个的相关问题,本文首席CTO笔记就来为大家做个详细解答,供大家参考,希望对大家有所帮助!一起来看看吧!
pythonpy文件同时开两个线程可以吗可以的。
Python多线程
多线程类似于同时执行多个不同程序,多线程运行有如下优点:
使用线程可以把占据长时间的程序中的任务放到后台去处理。
用户界面可以更加吸引人,这样比如用户点击了一个按钮去触发某些事件的处理,可以弹出一个进度条来显示处理的进度
程序的运行速度可能加快
在一些等待的任务实现上如用户输入、文件读写和网络收发数据等,线程就比较有用了。在这种情况下我们可以释放一些珍贵的资源如内存占用等等。
线程在执行过程中与进程还是有区别的。每个独立的进程有一个程序运行的入口、顺序执行序列和程序的出口。但是线程不能够独立执行,必须依存在应用程序中,由应用程序提供多个线程执行控制。
每个线程都有他自己的一组CPU寄存器,称为线程的上下文,该上下文反映了线程上次运行该线程的CPU寄存器的状态。
指令指针和堆栈指针寄存器是线程上下文中两个最重要的寄存器,线程总是在进程得到上下文中运行的,这些地址都用于标志拥有线程的进程地址空间中的内存。
线程可以被抢占(中断)。
在其他线程正在运行时,线程可以暂时搁置(也称为睡眠)--这就是线程的退让。
python多进程中同一时间到底有几个线程在运行
python多进程中同一时间到底有几个线程在运行
一般是一个,因为没有真正意义上的多线程,只是在多线程中快速切换
python中多进程+协程的使用以及为什么要用它前面讲了为什么python里推荐用多进程而不是多线程,但是多进程也有其自己的*:相比线程更加笨重、切换耗时更长,并且在python的多进程下,进程数量不推荐超过CPU核心数(一个进程只有一个GIL,所以一个进程只能跑满一个CPU),因为一个进程占用一个CPU时能充分利用机器的性能,但是进程多了就会出现频繁的进程切换,反而得不偿失。
不过特殊情况(特指IO密集型任务)下,多线程是比多进程好用的。
举个例子:给你200W条url,需要你把每个url对应的页面抓取保存起来,这种时候,单单使用多进程,效果肯定是很差的。为什么呢?
例如每次请求的等待时间是2秒,那么如下(忽略cpu计算时间):
1、单进程+单线程:需要2秒*200W=400W秒==1111.11个小时==46.3天,这个速度明显是不能接受的
2、单进程+多线程:例如我们在这个进程中开了10个多线程,比1中能够提升10倍速度,也就是大约4.63天能够完成200W条抓取,请注意,这里的实际执行是:线程1遇见了阻塞,CPU切换到线程2去执行,遇见阻塞又切换到线程3等等,10个线程都阻塞后,这个进程就阻塞了,而直到某个线程阻塞完成后,这个进程才能继续执行,所以速度上提升大约能到10倍(这里忽略了线程切换带来的开销,实际上的提升应该是不能达到10倍的),但是需要考虑的是线程的切换也是有开销的,所以不能无限的启动多线程(开200W个线程肯定是不靠谱的)
3、多进程+多线程:这里就厉害了,一般来说也有很多人用这个方法,多进程下,每个进程都能占一个cpu,而多线程从一定程度上绕过了阻塞的等待,所以比单进程下的多线程又更好使了,例如我们开10个进程,每个进程里开20W个线程,执行的速度理论上是比单进程开200W个线程快10倍以上的(为什么是10倍以上而不是10倍,主要是cpu切换200W个线程的消耗肯定比切换20W个进程大得多,考虑到这部分开销,所以是10倍以上)。
还有更好的方法吗?答案是肯定的,它就是:
4、协程,使用它之前我们先讲讲what/why/how(它是什么/为什么用它/怎么使用它)
what:
协程是一种用户级的轻量级线程。协程拥有自己的寄存器上下文和栈。协程调度切换时,将寄存器上下文和栈保存到其他地方,在切回来的时候,恢复先前保存的寄存器上下文和栈。因此:
协程能保留上一次调用时的状态(即所有局部状态的一个特定组合),每次过程重入时,就相当于进入上一次调用的状态,换种说法:进入上一次离开时所处逻辑流的位置。
在并发编程中,协程与线程类似,每个协程表示一个执行单元,有自己的本地数据,与其它协程共享全局数据和其它资源。
why:
目前主流语言基本上都选择了多线程作为并发设施,与线程相关的概念是抢占式多任务(Preemptivemultitasking),而与协程相关的是协作式多任务。
不管是进程还是线程,每次阻塞、切换都需要陷入系统调用(systemcall),先让CPU跑操作系统的调度程序,然后再由调度程序决定该跑哪一个进程(线程)。
而且由于抢占式调度执行顺序无法确定的特点,使用线程时需要非常小心地处理同步问题,而协程完全不存在这个问题(事件驱动和异步程序也有同样的优点)。
因为协程是用户自己来编写调度逻辑的,对CPU来说,协程其实是单线程,所以CPU不用去考虑怎么调度、切换上下文,这就省去了CPU的切换开销,所以协程在一定程度上又好于多线程。
how:
python里面怎么使用协程?答案是使用gevent,使用方法:看这里
使用协程,可以不受线程开销的*,我尝试过一次把20W条url放在单进程的协程里执行,完全没问题。
所以最推荐的方法,是多进程+协程(可以看作是每个进程里都是单线程,而这个单线程是协程化的)
多进程+协程下,避开了CPU切换的开销,又能把多个CPU充分利用起来,这种方式对于数据量较大的爬虫还有文件读写之类的效率提升是巨大的。
小例子:
[python]?viewplain?copy
#-*-?coding=utf-8?-*-
import?requests
from?multiprocessing?import?Process
import?gevent
from?gevent?import?monkey;?monkey.patch_all()
import?sys
reload(sys)
sys.setdefaultencoding('utf8')
def?fetch(url):
try:
s?=?requests.Session()
r?=?s.get(url,timeout=1)#在这里抓取页面
except?Exception,e:
print?e
return?''
def?process_start(url_list):
tasks?=?[]
for?url?in?url_list:
tasks.append(gevent.spawn(fetch,url))
gevent.joinall(tasks)#使用协程来执行
def?task_start(filepath,flag?=?100000):#每10W条url启动一个进程
with?open(filepath,'r')?as?reader:#从给定的文件中读取url
url?=?reader.readline().strip()
url_list?=?[]#这个list用于存放协程任务
i?=?0?#计数器,记录添加了多少个url到协程队列
while?url!='':
i?+=?1
url_list.append(url)#每次读取出url,将url添加到队列
if?i?==?flag:#一定数量的url就启动一个进程并执行
p?=?Process(target=process_start,args=(url_list,))
p.start()
url_list?=?[]?#重置url队列
i?=?0?#重置计数器
url?=?reader.readline().strip()
if?url_list?not?[]:#若退出循环后任务队列里还有url剩余
p?=?Process(target=process_start,args=(url_list,))#把剩余的url全都放到最后这个进程来执行
p.start()
if?__name__?==?'__main__':
task_start('./testData.txt')#读取指定文件
细心的同学会发现:上面的例子中隐藏了一个问题:进程的数量会随着url数量的增加而不断增加,我们在这里不使用进程池multiprocessing.Pool来控制进程数量的原因是multiprocessing.Pool和gevent有冲突不能同时使用,但是有兴趣的同学可以研究一下gevent.pool这个协程池。
python中,两个函数都开启了10个线程,执行顺序是怎样的?一共是20个线程
执行次序的话,有可能是相互交叉的,不一定是依次执行
还要注意python的线程有时被称为伪线程
python最大支持多少线程?那啥,python线程太慢了,想并发去用greenlet吧,快,写起来还方便。
如果加锁同步的话,线程多了反而变慢也有可能。
ulimit-s返回线程栈大小,我的默认是8192,用内存大小除以它就得到理论上的线程数吧。
python多线程并发数量控制python多线程如果不进行并发数量控制,在启动线程数量多到一定程度后,会造成线程无法启动的错误。
控制多线程并发数量的方法有好几钟,下面介绍用queue控制多线程并发数量的方法。python3
结语:以上就是首席CTO笔记为大家整理的关于python多线程能开多少个的全部内容了,感谢您花时间阅读本站内容,希望对您有所帮助,更多关于python多线程能开多少个的相关内容别忘了在本站进行查找喔。