python多线程多进程
一、線程&進(jìn)程
對(duì)于操作系統(tǒng)來(lái)說(shuō),一個(gè)任務(wù)就是一個(gè)進(jìn)程(Process),比如打開一個(gè)瀏覽器就是啟動(dòng)一個(gè)瀏覽器進(jìn)程,打開一個(gè)記事本就啟動(dòng)了一個(gè)記事本進(jìn)程,打開兩個(gè)記事本就啟動(dòng)了兩個(gè)記事本進(jìn)程,打開一個(gè)Word就啟動(dòng)了一個(gè)Word進(jìn)程。進(jìn)程是很多資源的集合。
?
有些進(jìn)程還不止同時(shí)干一件事,比如Word,它可以同時(shí)進(jìn)行打字、拼寫檢查、打印等事情。在一個(gè)進(jìn)程內(nèi)部,要同時(shí)干多件事,就需要同時(shí)運(yùn)行多個(gè)“子任務(wù)”,我們把進(jìn)程內(nèi)的這些“子任務(wù)”稱為線程(Thread)。
由于每個(gè)進(jìn)程至少要干一件事,所以,一個(gè)進(jìn)程至少有一個(gè)線程。當(dāng)然,像Word這種復(fù)雜的進(jìn)程可以有多個(gè)線程,多個(gè)線程可以同時(shí)執(zhí)行,多線程的執(zhí)行方式和多進(jìn)程是一樣的,也是由操作系統(tǒng)在多個(gè)線程之間快速切換,讓每個(gè)線程都短暫地交替運(yùn)行,看起來(lái)就像同時(shí)執(zhí)行一樣。當(dāng)然,真正地同時(shí)執(zhí)行多線程需要多核CPU才可能實(shí)現(xiàn)。線程是最小的執(zhí)行單元,而進(jìn)程由至少一個(gè)線程組成。
我們?cè)谧鍪虑榈臅r(shí)候,一個(gè)人做是比較慢的,如果多個(gè)人一起來(lái)做的話,就比較快了,程序也是一樣的,我們想運(yùn)行的速度快一點(diǎn)的話,就得使用多進(jìn)程,或者多線程,在python里面,多線程被很多人詬病,為什么呢,因?yàn)镻ython的解釋器使用了GIL的一個(gè)叫全局解釋器鎖,它不能利用多核CPU,只能運(yùn)行在一個(gè)cpu上面,但是你在運(yùn)行程序的時(shí)候,看起來(lái)好像還是在一起運(yùn)行的,是因?yàn)椴僮飨到y(tǒng)輪流讓各個(gè)任務(wù)交替執(zhí)行,任務(wù)1執(zhí)行0.01秒,切換到任務(wù)2,任務(wù)2執(zhí)行0.01秒,再切換到任務(wù)3,執(zhí)行0.01秒……這樣反復(fù)執(zhí)行下去。表面上看,每個(gè)任務(wù)都是交替執(zhí)行的,但是,由于CPU的執(zhí)行速度實(shí)在是太快了,我們感覺就像所有任務(wù)都在同時(shí)執(zhí)行一樣。這個(gè)叫做上下文切換。
二、多線程,python中的多線程使用theading模塊
下面是一個(gè)簡(jiǎn)單多線程
| 1 2 3 4 5 6 7 8 9 10 11 12 13 | import?threading import?time def?sayhi(num):?#定義每個(gè)線程要運(yùn)行的函數(shù) print("running?on?number:%s"?%num) time.sleep(3) if?__name__?==?'__main__': t1?=?threading.Thread(target=sayhi,args=(1,))?#生成一個(gè)線程實(shí)例 t2?=?threading.Thread(target=sayhi,args=(2,))?#生成另一個(gè)線程實(shí)例 t1.start()?#啟動(dòng)線程 t2.start()?#啟動(dòng)另一個(gè)線程 |
下面是另一種啟動(dòng)多線程的方式,繼承式
| 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 | import?threading import?time class?MyThread(threading.Thread): def?__init__(self,num): threading.Thread.__init__(self) self.num?=?num def?run(self):#定義每個(gè)線程要運(yùn)行的函數(shù) print("running?on?number:%s"?%self.num) time.sleep(3) if?__name__?==?'__main__': t1?=?MyThread(1) t2?=?MyThread(2) t1.start() t2.start() |
這兩種方式?jīng)]有什么區(qū)別,兩種寫法而已,我個(gè)人喜歡用第一種,更簡(jiǎn)單一些。
線程等待,多線程在運(yùn)行的時(shí)候,每個(gè)線程都是獨(dú)立運(yùn)行的,不受其他的線程干擾,如果想在哪個(gè)線程運(yùn)行完之后,再做其他操作的話,就得等待它完成,那怎么等待呢,使用join,等待線程結(jié)束
| 1 2 3 4 5 6 7 8 9 10 11 12 13 14 | import?threading import?time def?run(): print('qqq') time.sleep(1) print('done!') lis?=?[] for?i?in?range(5): t?=?threading.Thread(target=run) lis.append(t) t.start() for?t?in?lis: t.join() print('over') |
守護(hù)線程,什么是守護(hù)線程呢,就相當(dāng)于你是一個(gè)國(guó)王(非守護(hù)線程),然后你有很多仆人(守護(hù)線程),這些仆人都是為你服務(wù)的,一但你死了,那么你的仆人都給你陪葬。
| 1 2 3 4 5 6 7 8 9 10 11 | import?threading import?time def?run(): print('qqq') time.sleep(1) print('done!') for?i?in?range(5): t?=?threading.Thread(target=run) t.setDaemon(True) t.start() print('over') |
線程鎖,線程鎖就是,很多線程一起在操作一個(gè)數(shù)據(jù)的時(shí)候,可能會(huì)有問(wèn)題,就要把這個(gè)數(shù)據(jù)加個(gè)鎖,同一時(shí)間只能有一個(gè)線程操作這個(gè)數(shù)據(jù)。
| 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 | import?threading from?threading?import?Lock num?=?0 lock?=?Lock()#申請(qǐng)一把鎖 def?run(): global?num lock.acquire()#加鎖 num+=1 lock.release()#解鎖 lis?=?[] for?i?in?range(5): t?=?threading.Thread(target=run) t.start() lis.append(t) for?t?in?lis: t.join() print('over',num) |
下面來(lái)個(gè)簡(jiǎn)單的爬蟲,看下多線程的效果
| 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 | import?threading import?requests,time urls??={ "baidu":'http://www.baidu.com', "blog":'http://www.nnzhp.cn', "besttest":'http://www.besttest.cn', "taobao":"http://www.taobao.com", "jd":"http://www.jd.com", } def?run(name,url): res?=?requests.get(url) with?open(name+'.html','w',encoding=res.encoding)?as?fw: fw.write(res.text) start_time?=?time.time() lis?=?[] for?url?in?urls: t?=?threading.Thread(target=run,args=(url,urls[url])) t.start() lis.append(t) for?t?in?lis: t.join() end_time?=?time.time() print('run?time?is?%s'%(end_time-start_time)) #下面是單線程的執(zhí)行時(shí)間 #?start_time?=?time.time() #?for?url?in?urls: #?????run(url,urls[url]) #?end_time?=?time.time() #?print('run?time?is?%s'%(end_time-start_time)) |
三、多進(jìn)程,上面說(shuō)了Python里面的多線程,是不能利用多核CPU的,如果想利用多核CPU的話,就得使用多進(jìn)程,python中多進(jìn)程使用multiprocessing模塊。
| 1 2 3 4 5 6 7 8 | from?multiprocessing?import?Process import?time def?f(name): time.sleep(2) print('hello',?name)? p?=?Process(target=f,?args=('niu',)) p.start() p.join() |
?
轉(zhuǎn)載于:https://www.cnblogs.com/chunyanxu/p/8732576.html
總結(jié)
以上是生活随笔為你收集整理的python多线程多进程的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問(wèn)題。
- 上一篇: Redmi K50至尊版上手:性能调校超
- 下一篇: python_线程、进程和协程