python 進程池的使用

進程同步

進程的數據是獨立存在的,進程也能加鎖。python

from multiprocessing import Process, Lock

def f(l,i):
    l.acquire()
    print('hello world',i)
    l.release()


if __name__ =='__main__':
    lock = Lock()   #得到鎖的實例
    for i in range(10):
        Process(target=f,args=(lock,i)).start() #啓動進程,而且把鎖的實例傳到進程

 運行結果數據庫

hello world 0
hello world 2
hello world 1
hello world 3
hello world 6
hello world 7
hello world 8
hello world 4
hello world 5
hello world 9

 進程爲何要加鎖?app

由於進程的數據是獨立存在的,並不會共享同一塊數據。可是有些資源是共享的,好比顯示器。若是每一個進程都要輸出內容,那麼顯示的就很亂了,這個鎖就是在某個進程獨自輸出的時候獨佔,不會被其它進程干擾。異步

進程池

 

apply  同步執行 串行async

apply_async  異步執行 並行函數

 

from multiprocessing import Process, Pool,freeze_support
import time
import os

def Foo(i):
    time.sleep(2)
    print('當前進程',os.getpid())
    return i + 100

def Bar(arg):
    print("-->exec done:",arg)

if __name__ =='__main__':
    freeze_support()
    pool = Pool(processes=5) #容許進程池中同時放入5個進程

    for i in range(10):
        #pool.apply_async(func=Foo,args=(i,),callback=Bar)
        pool.apply(func=Foo,args=(i,))

    print('end')
    pool.close()
    pool.join() #進程池中進程執行完畢後在關閉,若是註釋,那麼程序直接關閉。.join()

 

 運行結果ui

當前進程 5816  #sleep 2s  打印
當前進程 8124  #sleep 2s  打印
當前進程 6488  #sleep 2s  打印
當前進程 5356
當前進程 7036
當前進程 5816
當前進程 8124
當前進程 6488
當前進程 5356
當前進程 7036
end

 以上是同步執行,程序顯示的效果是串行化執行。spa

 

並行化blog

from multiprocessing import Process, Pool,freeze_support
import time
import os

def Foo(i):
    time.sleep(2)
    print('當前進程',os.getpid())
    return i + 100

def Bar(arg):
    print("-->exec done:",arg)

if __name__ =='__main__':
    freeze_support()
    pool = Pool(processes=5) #容許進程池中同時放入5個進程

    for i in range(10):
        pool.apply_async(func=Foo,args=(i,),callback=Bar)
        #pool.apply(func=Foo,args=(i,))

    print('end')
    pool.close()
    pool.join() #進程池中進程執行完畢後在關閉,若是註釋,那麼程序直接關閉。.join()

 運行結果進程

end
當前進程 6060  #一次打印5個
當前進程 6952
-->exec done: 100
-->exec done: 101
當前進程 3388
-->exec done: 102
當前進程 1600
-->exec done: 103
當前進程 7648
-->exec done: 104
當前進程 6060
當前進程 6952
-->exec done: 105
-->exec done: 106
當前進程 3388
-->exec done: 107
當前進程 1600
-->exec done: 108
當前進程 7648
-->exec done: 109

callback() 回調函數,子進程執行完func,以後在調用的函數。 那麼這個函數是子進程調用的仍是主進程調用的?

from multiprocessing import Process, Pool,freeze_support
import time
import os

def Foo(i):
    time.sleep(2)
    print('當前進程',os.getpid())
    return i + 100

def Bar(arg):
    print("-->exec done:",arg,os.getpid())  #顯示調用當前函數的進程id

if __name__ =='__main__':
    freeze_support()
    pool = Pool(processes=5) #容許進程池中同時放入5個進程
    print("主進程",os.getpid())  #顯示主進程id
    for i in range(10):
        pool.apply_async(func=Foo,args=(i,),callback=Bar)
        #pool.apply(func=Foo,args=(i,))

    print('end')
    pool.close()
    pool.join() #進程池中進程執行完畢後在關閉,若是註釋,那麼程序直接關閉。.join()

 運行結果

主進程 7052
end
當前進程 7992
當前進程 1848
-->exec done: 101 7052
-->exec done: 100 7052
當前進程 2212
-->exec done: 102 7052
當前進程 980
當前進程 8064
-->exec done: 103 7052
-->exec done: 104 7052
當前進程 7992
-->exec done: 105 7052
當前進程 1848
-->exec done: 106 7052
當前進程 2212
-->exec done: 107 7052
當前進程 8064
當前進程 980
-->exec done: 109 7052
-->exec done: 108 7052

 這裏能夠看到是主進程調用的回調,這些寫的優勢是,好比子進程作了數據備份要寫到數據庫,若是每一個子進程都在執行的函數裏面寫,那麼每一個進程都要鏈接一次數據庫,用主進程調用的方式就是能夠省去這麼多的鏈接數據庫的操做。效率更高。

相關文章
相關標籤/搜索