1. 程式人生 > >python多執行緒、多程序、協程的使用

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密集的任務下,各個之間的區別就會顯現,這裡就不做介紹。