python多執行緒、多程序、協程的使用
本文主要介紹多執行緒、多程序、協程的最常見使用,每個的詳細說明與介紹有時間會在以後的隨筆中體現。
一、多執行緒
1.python通過兩個標準庫thread和threading提供對執行緒的支援。thread提供了低級別的、原始的執行緒以及一個簡單的鎖。threading通過對thread模組進行二次封裝,提供了更方便的API來操作執行緒。接下來只介紹threading的常見用法。
2.使用
import threading import time def Traversal_5(interval): for i in xrange(5): print 'Traversal_5:',i time.sleep(interval) def Traversal_10(interval): for i in xrange(10): print 'Traversal_10:',i time.sleep(interval) if __name__ == '__main__': print 'start time:' t1 = int(time.time()) tasks=[Traversal_5,Traversal_10] threads = [] for task in tasks: t = threading.Thread(target=task,args=(1,)) threads.append(t) for t in threads: t.setDaemon(True) t.start() for t in threads: t.join() print 'end main total time:',int(time.time())-t1
3.結果
4.結果分析
單執行緒執行這完兩個函式至少應該需要15秒,多執行緒情況下,兩個函式同時執行,總共用時是取最長的Traversal_10這個函式的時間
二、多程序
1.由於GIL的存在,python中的多執行緒其實並不是真正的多執行緒,如果想要充分地使用多核CPU的資源,在python中大部分情況需要使用多程序。Python提供了非常好用的多程序包multiprocessing,與threading.Thread類似,它可以利用multiprocessing.Process物件來建立一個程序。接下來只介紹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): for i in xrange(5): print 'process name:',name,'\tindex:',i time.sleep(interval) if __name__ == '__main__': print 'start time:' t1 = int(time.time()) jobs = [] for x in xrange(2): p = multiprocessing.Process(target = Traversal, args=(1,'Traversal_'+str(x))) p.start() jobs.append(p) for job in jobs: job.join() print 'end main total time:',int(time.time())-t1
3.結果
4.結果分析
此程式相當於遍歷兩次0-5的函式,按理說,時間應該是10秒,因為開了2個程序,所以總花時和一次遍歷時間相等
三、協程
1.協程,又稱微執行緒,纖程。協程的特點在於是一個執行緒執行,那和多執行緒比,協程有何優勢?最大的優勢就是協程極高的執行效率。因為子程式切換不是執行緒切換,而是由程式自身控制,因此,沒有執行緒切換的開銷,和多執行緒比,執行緒數量越多,協程的效能優勢就越明顯。第三方的gevent為Python提供了比較完善的協程支援。接下來只介紹gevent用法
2.使用
from gevent import monkey; monkey.patch_all(); from gevent.pool import Pool import time def Traversal(job): print 'job:',job time.sleep(1) if __name__ == '__main__': print 'start time:' t1 = int(time.time()) jobs = [i for i in xrange(10)] pool = Pool(5) pool.map(Traversal, jobs) print 'end main total time:',int(time.time())-t1
3.結果
3.結果分析
此程式本質是遍歷0-10之間的數,應該用時10秒,由於使用了協程,開啟了5個池,所以時間減少到2秒,大大減少執行時間。
四、多程序+協程
1.因為協程是一個執行緒執行,那怎麼利用多核CPU呢?最簡單的方法是多程序+協程,既充分利用多核,又充分發揮協程的高效率,可獲得極高的效能。
2.使用
import multiprocessing from gevent import monkey; monkey.patch_all(); from gevent.pool import Pool import 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 = [i for i in xrange(5)] pool = Pool(5) pool.map(Traver, jobs) if __name__ == '__main__': print 'start time:' t1 = int(time.time()) jobs = [] for x in xrange(2): p = multiprocessing.Process(target = Traversal, args=(1,'Traversal_'+str(x))) p.start() jobs.append(p) for job in jobs: job.join() print 'end main total time:',int(time.time())-t1
3.結果
4.結果分析
此程式本質上是遍歷2次0-5之間資料,應該使用10秒才能執行完,由於開啟了兩個執行緒和5個池的協程,結果1秒就執行完了。
五、總結
從以上小例子看,多程序、多執行緒和協程沒有啥差別,本文也只是主要介紹其用法。但是,要是在IO密集和CPU密集的任務下,各個之間的區別就會顯現,這裡就不做介紹。