python中進程池的應用
#原創,轉載請聯系
假設我們寫的一個程序需要運行100個子進程的時候,那麽寫程序時,不可能循環創建銷毀100個進程吧?進程的創建與銷毀是很耗系統的資源的。
進程池的作用就體現出來了。
進程池可以控制進程的數量,重復利用進程對象,減少創建和銷毀進程的開銷。
-----------------------------------------------------------------------------------------我是一條分割線----------------------------------------------------------------------------------------------------
1.創建進程池
pool = multiprocessing.Pool()
創建進程池可以接收一個參數,這個參數可以設置進程池的最大值。就是指定有幾個子進程在“同時”進行。(為什麽說是“同時”,因為在並發的情況下,子進程和主進程是按照時間片輪尋的方式執行的,只是切換得過快,並不是真的一起運行。)
-----------------------------------------------------------------------------------------我是一條分割線----------------------------------------------------------------------------------------------------
2.進程池的應用
import multiprocessing import os import random import time def run_time(index): start_time = time.time() time.sleep(random.random()) print("任務%d 任務id為%d 任務運行的時間為%0.2f" % (index,os.getpid(), time.time()-start_time)) if __name__ == ‘__main__‘: pool = multiprocessing.Pool(3) for i in range(10): pool.apply_async(func=run_time,args=(i,)) pool.close() pool.join() print("結束標誌")
輸出:
任務2 任務id為3191 任務運行的時間為0.29
任務1 任務id為3190 任務運行的時間為0.33
任務0 任務id為3189 任務運行的時間為0.45
任務3 任務id為3191 任務運行的時間為0.41
任務4 任務id為3190 任務運行的時間為0.39
任務5 任務id為3189 任務運行的時間為0.76
任務7 任務id為3190 任務運行的時間為0.52
任務6 任務id為3191 任務運行的時間為0.80
任務8 任務id為3189 任務運行的時間為0.56
任務9 任務id為3190 任務運行的時間為0.80
結束標誌
-----------------------------------------------------------------------------------------我是一條分割線----------------------------------------------------------------------------------------------------
3.進程池的進程默認都是守護進程
進程池的子進程都是由主進程創建的,且默認都是守護進程。所以當主進程執行完之後,進程池的子進程全部都被中斷。如果需要執行完進程池的子進程,才結束程序,需要加上兩句代碼。
pool.close() # 必須先關閉進程池,不再讓它接收新的進程,才能進行下一步的阻塞。(已經在排隊的進程不算新進程了!例如上面的例子,
10個子進程已經在進程池排隊,所以join方法會阻塞直到10個子進程執行完成。) pool.join()
上面的例子,如果沒有這兩句代碼,輸出會變成下面的結果
import multiprocessing import os import random import time def run_time(index): start_time = time.time() time.sleep(random.random()) print("任務%d 任務id為%d 任務運行的時間為%0.2f" % (index,os.getpid(), time.time()-start_time)) if __name__ == ‘__main__‘: pool = multiprocessing.Pool(3) for i in range(10): pool.apply_async(func=run_time,args=(i,)) print("結束標誌")
輸出:
結束標誌
進程池排隊的10個進程,都是守護進程。還沒來得及運行,主進程運行了,然後中斷了進程池所有的子進程,因次子進程並沒有輸出。
-----------------------------------------------------------------------------------------我是一條分割線----------------------------------------------------------------------------------------------------
4.進程池中子進程之間的通信。
關於進程間的通信,可以看我的另一篇博客。https://www.cnblogs.com/chichung/p/9533227.html
那麽,進程池中的子進程之間怎麽進行通信呢?
我們來在進程池創建兩個子進程,然後讓一個子進程把數據放在隊列,另外一個子進程在隊列裏取數據。
import multiprocessing import time def send_data(queue): for i in "python": queue.put(i) print("把%s放進隊列裏" % i) def recv_data(queue): while not queue.empty(): data = queue.get() print("在隊列裏取得%s" % data) if __name__ == ‘__main__‘: q = multiprocessing.Manager().Queue(5) # 進程池之間的通信中間要加Manager(),單純進程間的通信並不用,這是最大的區別。 pool = multiprocessing.Pool(2) pool.apply_async(func=send_data,args=(q,)) time.sleep(1) pool.apply_async(func=recv_data,args=(q,)) time.sleep(1) pool.close() pool.join() print("結束標誌")
輸出:
把p放進隊列裏
把y放進隊列裏
把t放進隊列裏
把h放進隊列裏
把o放進隊列裏
在隊列裏取得p
把n放進隊列裏
在隊列裏取得y
在隊列裏取得t
在隊列裏取得h
在隊列裏取得o
在隊列裏取得n
結束標誌
進程池裏面子進程的通信也是用到Queue隊列,但是創建的方式稍微有點不同,上面代碼註釋那裏已經提出。
python中進程池的應用