python多線程蹭睡、多進(jìn)程衍菱、協(xié)程的使用
本文主要介紹多線程、多進(jìn)程肩豁、協(xié)程的最常見使用脊串,每個(gè)的詳細(xì)說明與介紹有時(shí)間會在以后的隨筆中體現(xiàn)。
一清钥、多線程
1.python通過兩個(gè)標(biāo)準(zhǔn)庫thread和threading提供對線程的支持琼锋。thread提供了低級別的、原始的線程以及一個(gè)簡單的鎖祟昭。threading通過對thread模塊進(jìn)行二次封裝缕坎,提供了更方便的API來操作線程。接下來只介紹threading的常見用法篡悟。
2.使用
import threadingimport time def Traversal_5(interval):
? ? foriinxrange(5):
? ? ? ? print'Traversal_5:',i
? ? ? ? time.sleep(interval)def Traversal_10(interval):
? ? foriinxrange(10):
? ? ? ? print'Traversal_10:',i
? ? ? ? time.sleep(interval)if__name__=='__main__':
? ? print'start time:'? ? t1 = int(time.time())
? ? tasks=[Traversal_5,Traversal_10]
? ? threads = []
? ? fortaskin tasks:
? ? ? ? t = threading.Thread(target=task,args=(1,))
? ? ? ? threads.append(t)
? ? fortin threads:
? ? ? ? t.setDaemon(True)
? ? ? ? t.start()
? ? fortin threads:
? ? ? ? t.join()
? ? print'end main total time:',int(time.time())-t1
3.結(jié)果
4.結(jié)果分析
單線程運(yùn)行這完兩個(gè)函數(shù)至少應(yīng)該需要15秒谜叹,多線程情況下,兩個(gè)函數(shù)同時(shí)運(yùn)行搬葬,總共用時(shí)是取最長的Traversal_10這個(gè)函數(shù)的時(shí)間
二荷腊、多進(jìn)程
1.由于GIL的存在,python中的多線程其實(shí)并不是真正的多線程急凰,如果想要充分地使用多核CPU的資源女仰,在python中大部分情況需要使用多進(jìn)程。Python提供了非常好用的多進(jìn)程包multiprocessing抡锈,與threading.Thread類似疾忍,它可以利用multiprocessing.Process對象來創(chuàng)建一個(gè)進(jìn)程。接下來只介紹multiprocessing的常見用法企孩。
2.使用
import multiprocessing import time class Traversal(object):
? ? def__init__(self,interval, name):
? ? ? ? self.interval = interval
? ? ? ? self.name = name
? ? ? ? self._rungevent(self.interval, self.name)
? ? def _rungevent(self, interval, name):
? ? ? ? foriinxrange(5):
? ? ? ? ? ? print'process name:',name,'\tindex:',i
? ? ? ? ? ? time.sleep(interval)if__name__=='__main__':
? ? print'start time:'? ? t1 = int(time.time())
? ? jobs = []
? ? forxinxrange(2):
? ? ? ? p = multiprocessing.Process(target = Traversal, args=(1,'Traversal_'+str(x)))
? ? ? ? p.start()
? ? ? ? jobs.append(p)
? ? forjobin jobs:
? ? ? ? job.join()
? ? print'end main total time:',int(time.time())-t1
3.結(jié)果
4.結(jié)果分析
此程序相當(dāng)于遍歷兩次0-5的函數(shù)锭碳,按理說,時(shí)間應(yīng)該是10秒勿璃,因?yàn)殚_了2個(gè)進(jìn)程擒抛,所以總花時(shí)和一次遍歷時(shí)間相等
三、協(xié)程
1.協(xié)程补疑,又稱微線程歧沪,纖程。協(xié)程的特點(diǎn)在于是一個(gè)線程執(zhí)行莲组,那和多線程比诊胞,協(xié)程有何優(yōu)勢?最大的優(yōu)勢就是協(xié)程極高的執(zhí)行效率。因?yàn)樽映绦蚯袚Q不是線程切換撵孤,而是由程序自身控制迈着,因此,沒有線程切換的開銷邪码,和多線程比裕菠,線程數(shù)量越多,協(xié)程的性能優(yōu)勢就越明顯闭专。第三方的gevent為Python提供了比較完善的協(xié)程支持奴潘。接下來只介紹gevent用法
2.使用
fromgeventimport monkey; monkey.patch_all(); fromgevent.poolimport Pool import time def Traversal(job):
? ? print'job:',job
? ? time.sleep(1)if__name__=='__main__':
? ? print'start time:'? ? t1 = int(time.time())
? ? jobs = [iforiinxrange(10)]
? ? pool = Pool(5)
? ? pool.map(Traversal, jobs)
? ? print'end main total time:',int(time.time())-t1
3.結(jié)果
3.結(jié)果分析
此程序本質(zhì)是遍歷0-10之間的數(shù),應(yīng)該用時(shí)10秒影钉,由于使用了協(xié)程画髓,開啟了5個(gè)池,所以時(shí)間減少到2秒平委,大大減少運(yùn)行時(shí)間奈虾。
四、多進(jìn)程+協(xié)程
1.因?yàn)閰f(xié)程是一個(gè)線程執(zhí)行肆汹,那怎么利用多核CPU呢愚墓?最簡單的方法是多進(jìn)程+協(xié)程,既充分利用多核昂勉,又充分發(fā)揮協(xié)程的高效率浪册,可獲得極高的性能。
2.使用
import multiprocessing fromgeventimport monkey; monkey.patch_all(); fromgevent.poolimport Poolimport time def Traver(job):
? ? print'job:',job
? ? time.sleep(1)class Traversal(object):
? ? def__init__(self,interval, name):
? ? ? ? self.interval = interval
? ? ? ? self.name = name
? ? ? ? self._rungevent(self.interval, self.name)
? ? def _rungevent(self, interval, name):
? ? ? ? jobs = [iforiinxrange(5)]
? ? ? ? pool = Pool(5)
? ? ? ? pool.map(Traver, jobs) if__name__=='__main__':
? ? print'start time:'? ? t1 = int(time.time())
? ? jobs = []
? ? forxinxrange(2):
? ? ? ? p = multiprocessing.Process(target = Traversal, args=(1,'Traversal_'+str(x)))
? ? ? ? p.start()
? ? ? ? jobs.append(p)
? ? forjobin jobs:
? ? ? ? job.join()
? ? print'end main total time:',int(time.time())-t1
3.結(jié)果
4.結(jié)果分析
此程序本質(zhì)上是遍歷2次0-5之間數(shù)據(jù)岗照,應(yīng)該使用10秒才能運(yùn)行完村象,由于開啟了兩個(gè)線程和5個(gè)池的協(xié)程,結(jié)果1秒就運(yùn)行完了攒至。
五厚者、總結(jié)
從以上小例子看,多進(jìn)程迫吐、多線程和協(xié)程沒有啥差別库菲,本文也只是主要介紹其用法。但是志膀,要是在IO密集和CPU密集的任務(wù)下熙宇,各個(gè)之間的區(qū)別就會顯現(xiàn),這里就不做介紹溉浙。