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

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM