1. 程式人生 > >Process類,Thread類,Pool類,gevent類,ProcessPoolExecutor,ThreadPoolExecutor的用法比較

Process類,Thread類,Pool類,gevent類,ProcessPoolExecutor,ThreadPoolExecutor的用法比較

rabl event 多進程 用法比較 cut 並且 multi 異步 eve

一 Process類

  multiprocessing模塊下的一個類

  創建子進程。

  有兩種方法

  方法一

技術分享圖片
from multiprocessing import Process
import os
def foo():
    print(‘%s from foo‘%os.getpid())
def bar():
    print(‘%s from bar‘ % os.getpid())
if __name__ == ‘__main__‘:
    p1=Process(target=foo)
    p2=Process(target=bar)
    p1.start()
    p2.start()
    p1.join()
    p2.join()
    print(‘%s over‘%os.getpid())
技術分享圖片

  輸出: 

13524 from foo
12848 from bar
12696 over

  方法二

技術分享圖片
from multiprocessing import Process
import os
class Myprocess(Process):
    def __init__(self,name):
        super().__init__()
        self.name=name
    def run(self):
        print(‘%s from %s‘ % (os.getpid(),self.name))
if __name__ == ‘__main__‘:
    p1=Myprocess(‘foo‘)
    p2=Myprocess(‘bar‘)
    p1.start()
    p2.start()
    p1.join()
    p2.join()
    print(‘%s over‘ % os.getpid())
技術分享圖片

  輸出:

15260 from foo
5980 from bar
8844 over

二 Thread類

  threading模塊下的類

  創建線程

  有兩種方法

  與Process類一樣。

三 Pool類

  Pool類的方法:

    p=Pool()

    p.apply_async(),異步提交任務,生成ApplyResult對象

    p.close()

    p.join()

    ApplyResult.get(),從ApplyResult對象中獲取返回值。

技術分享圖片
from multiprocessing import Pool
import os,time
def foo():
    time.sleep(1)
    print(‘%s from foo‘%os.getpid())
    return ‘foo‘
def bar():
    time.sleep(2)
    print(‘%s from bar‘ % os.getpid())
    return ‘bar‘
if __name__ == ‘__main__‘:
    p=Pool()
    t1=time.time()
    res1=p.apply_async(foo)
    res2=p.apply_async(bar)
    p.close()
    p.join()
    print(res1)
    print(time.time()-t1)          ##多出來的0.15秒是開啟進程所花費的時間
    t2=time.clock()
    print(res1.get())
    print(res2.get())
    print(time.clock()-t2)
技術分享圖片

  輸出:

技術分享圖片
12468 from foo
8832 from bar
<multiprocessing.pool.ApplyResult object at 0x00000126511CEE48>
2.1609864234924316
foo
bar
2.1880321932470032e-05
技術分享圖片

  map()方,比較常用。

  官方介紹:

Apply `func` to each element in `iterable`, collecting the results
        in a list that is returned.

  廢話少說,上代碼

技術分享圖片
import time
from multiprocessing import Pool

def foo(x):
    time.sleep(1)
    return x*x

if __name__ == ‘__main__‘:
    l = [1,2,3,4,5,6,7,8,9,10]
    t1 = time.time()
    p = Pool()
    print(time.time()-t1)
    res = p.map(foo,l) # 這行代碼表示所有的進行都已經執行完了,並且每個進程的結果都拿到,放在了res中
    print(time.time()-t1)   
    print(res,type(res))
    p.close()
    p.join()
    print(time.time()-t1)
技術分享圖片

  輸出:

0.14187192916870117
2.2597498893737793
[1, 4, 9, 16, 25, 36, 49, 64, 81, 100] <class ‘list‘>
2.401075601577759

四 gevent

  gevent是一個基於協程的Python網絡庫。

  單線程實現並發,協程。

  需要用到猴子補丁。

  方法:

    g1=gevent.spawn(func):提交任務,生成Greenlet對象--g1。

    g1.join(),阻塞,直到g1任務完成。

    g1.value。從Greenlet對象g1中獲取返回值。   

技術分享圖片
import gevent
from gevent import monkey;monkey.patch_all()
import os,time
from threading import current_thread
def foo():
    time.sleep(1)
    print(‘%s  %s from foo‘%(os.getpid(),current_thread().getName()))
def bar():
    time.sleep(2)
    print(‘%s  %s from bar‘ % (os.getpid(),current_thread().getName()))
t1=time.time()
g1=gevent.spawn(foo)
g2=gevent.spawn(bar)
print(g1,g2)
g1.join()
g2.join()
print(time.time()-t1)
技術分享圖片

  輸出:

<Greenlet at 0x1e3fc1396d0: foo> <Greenlet at 0x1e3fc139800: bar>
7536  DummyThread-1 from foo
7536  DummyThread-2 from bar
2.0017032623291016              #可以看到協程開啟進程花銷非常小。

五 ProcessPoolExecutor

  創建多進程

  concurrent.futures庫內的ProcessPoolExecutor類

  executor=ProcessPoolExecutor():生成一個ProcessPoolExecutor對象;

  future=executor.submit():提交任務,返回一個Future對象。

  executor.shutdown()。相當於Pool類中的close()和join()

  future.result():從Future對象中獲取其返回值。

技術分享圖片
from concurrent.futures import ProcessPoolExecutor,ThreadPoolExecutor
import os,time
from threading import current_thread
def foo():
    time.sleep(1)
    print(‘%s  %s from foo‘%(os.getpid(),current_thread().getName()))
    return ‘foo‘
def bar():
    time.sleep(2)
    print(‘%s  %s from bar‘ % (os.getpid(),current_thread().getName()))
    return ‘bar‘
if __name__ == ‘__main__‘:
    t1=time.time()
    executor=ProcessPoolExecutor()
    print(‘executor‘,executor)
    future1=executor.submit(foo)
    future2=executor.submit(bar)
    print(future1,future2)
    executor.shutdown()
    print(future1.result())
    print(future2.result())
    print(time.time()-t1)
技術分享圖片

  輸出:

6480  MainThread from foo
6756  MainThread from bar
foo
bar
2.7526917457580566                   #可以看到創建進程還是比較花費時間的

六 ThreadPoolExecutor()

  創建多線程

  concurrent.futures庫內的ProcessPoolExecutor類

  executor=ThreadPoolExecutor():生成一個ThreadPoolExecutor對象;

  future=executor.submit():提交任務,返回一個Future對象。

  executor.shutdown()。相當於Pool類中的close()和join()。

  future.result():從Future對象中獲取其返回值。

  

技術分享圖片
from concurrent.futures import ThreadPoolExecutor
import os,time
from threading import current_thread
def foo():
    time.sleep(1)
    print(‘%s  %s from foo‘%(os.getpid(),current_thread().getName()))
    return ‘foo‘
def bar():
    time.sleep(2)
    print(‘%s  %s from bar‘ % (os.getpid(),current_thread().getName()))
    return ‘bar‘
if __name__ == ‘__main__‘:
    t1=time.time()
    executor=ThreadPoolExecutor()
    print(‘executor‘,executor)
    future1=executor.submit(foo)
    future2=executor.submit(bar)
    print(future1,future2)
    executor.shutdown()
    print(future1.result())
    print(future2.result())
    print(time.time()-t1)
技術分享圖片

  輸出:

技術分享圖片
executor <concurrent.futures.thread.ThreadPoolExecutor object at 0x0000020073EAAAC8>
<Future at 0x20073eb4198 state=running> <Future at 0x20074176940 state=running>
4380  <concurrent.futures.thread.ThreadPoolExecutor object at 0x0000020073EAAAC8>_0 from foo         #可以看到進程號是一樣的
4380  <concurrent.futures.thread.ThreadPoolExecutor object at 0x0000020073EAAAC8>_1 from bar
foo
bar
2.001234531402588                     #相比較開啟進程,線程開啟的時間非常快,花銷非常小
技術分享圖片

Process類,Thread類,Pool類,gevent類,ProcessPoolExecutor,ThreadPoolExecutor的用法比較