天天看點

python攜程多核_python多線程、多程序、協程的使用

本文主要介紹多線程、多程序、協程的最常見使用,每個的詳細說明與介紹有時間會在以後的随筆中展現。

一、多線程

1.python通過兩個标準庫thread和threading提供對線程的支援。thread提供了低級别的、原始的線程以及一個簡單的鎖。threading通過對thread子產品進行二次封裝,提供了更友善的API來操作線程。接下來隻介紹threading的常見用法。

2.使用

importthreadingimporttimedefTraversal_5(interval):for i in xrange(5):print 'Traversal_5:',i

time.sleep(interval)defTraversal_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 intasks:

t= threading.Thread(target=task,args=(1,))

threads.append(t)for t inthreads:

t.setDaemon(True)

t.start()for t inthreads:

t.join()print 'end main total time:',int(time.time())-t1

3.結果

python攜程多核_python多線程、多程式、協程的使用

4.結果分析

單線程運作這完兩個函數至少應該需要15秒,多線程情況下,兩個函數同時運作,總共用時是取最長的Traversal_10這個函數的時間

二、多程序

1.由于GIL的存在,python中的多線程其實并不是真正的多線程,如果想要充分地使用多核CPU的資源,在python中大部分情況需要使用多程序。Python提供了非常好用的多程序包multiprocessing,與threading.Thread類似,它可以利用multiprocessing.Process對象來建立一個程序。接下來隻介紹multiprocessing的常見用法。

2.使用

importmultiprocessingimporttimeclassTraversal(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 injobs:

job.join()print 'end main total time:',int(time.time())-t1

3.結果

python攜程多核_python多線程、多程式、協程的使用

4.結果分析

此程式相當于周遊兩次0-5的函數,按理說,時間應該是10秒,因為開了2個程序,是以總花時和一次周遊時間相等

三、協程

1.協程,又稱微線程,纖程。協程的特點在于是一個線程執行,那和多線程比,協程有何優勢?最大的優勢就是協程極高的執行效率。因為子程式切換不是線程切換,而是由程式自身控制,是以,沒有線程切換的開銷,和多線程比,線程數量越多,協程的性能優勢就越明顯。第三方的gevent為Python提供了比較完善的協程支援。接下來隻介紹gevent用法

2.使用

from gevent importmonkey; monkey.patch_all();from gevent.pool importPoolimporttimedefTraversal(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.結果

python攜程多核_python多線程、多程式、協程的使用

3.結果分析

此程式本質是周遊0-10之間的數,應該用時10秒,由于使用了協程,開啟了5個池,是以時間減少到2秒,大大減少運作時間。

四、多程序+協程

1.因為協程是一個線程執行,那怎麼利用多核CPU呢?最簡單的方法是多程序+協程,既充分利用多核,又充分發揮協程的高效率,可獲得極高的性能。

2.使用

importmultiprocessingfrom gevent importmonkey; monkey.patch_all();from gevent.pool importPoolimporttimedefTraver(job):print 'job:',job

time.sleep(1)classTraversal(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 injobs:

job.join()print 'end main total time:',int(time.time())-t1

3.結果

python攜程多核_python多線程、多程式、協程的使用

4.結果分析

此程式本質上是周遊2次0-5之間資料,應該使用10秒才能運作完,由于開啟了兩個線程和5個池的協程,結果1秒就運作完了。

五、總結

從以上小例子看,多程序、多線程和協程沒有啥差别,本文也隻是主要介紹其用法。但是,要是在IO密集和CPU密集的任務下,各個之間的差別就會顯現,這裡就不做介紹。