學習使我快樂…… 接着上篇的講,上篇我們簡單了介紹了多線程的運用,其實在python中多線程是假的多線程,爲什麼這麼說呢,因爲python的解釋器在同一時刻只允許一個線程執行,不管你電腦有幾個核,單位時間多個核只能跑一個線程,然後時間片輪轉,其實可以理解爲在python的多線程是單核多線程,沒有完全利用電腦多核的資源,根本的原因是由全局解釋器鎖(GIL)引起的,要真正利用多核,除非重寫一個不帶GIL的解釋器,有興趣的童鞋可以用多線程寫個無限循環壓力測試看看CPU的運行情況,是否佔滿了100%。
what? 那我們在python中利用多核怎麼辦?所以就有了今天這篇進程池的運用……
python中調用進程池我們要引入對應的庫及方法:
from multiprocessing import Pool
首先我們還是跟多線程一樣定義一個run的方法:
#執行方法
def run(n):
time.sleep(1)
print("我是方法:{}".format(n))
爲了觀察方便,我們還是加入了延遲1秒,我們先定義一下進程池:
pool = Pool(processes=4)
processes這個參數表示的工作進程的個數,這個數值是由你電腦的CPU個數決定的,一般這個參數是小於或等於這個CPU數的,如果設置的過大,反而會執行更慢。上面的意思是一次執行4個進程,只要任務沒完,哪個進程先執行完就往這個進程加入新的任務,接下來我們循環生成10個任務:
for i in range(10):
pool.apply_async(func=run, args=(i, ))
這裏參數的方法跟多線程的方法基本類似,主要就是pool加入進程的方法,下面列舉下一般使用的方式:
1. apply (阻塞式的,效果就是跟單進程依次循環一樣)這個意思就是等待當前子進程執行完畢後,在執行下一個進程,個人感覺沒啥用~~!
2. apply_async (異步非阻塞式) 這個就是用得最多了,意思就是不用等待當前進程執行完畢,隨時根據系統調度來進行進程切換。
3. map 這個顧名思義,就是以map函數的形式傳遞參數,通常是數組的形式,比如:
pool.map(func=run,iterable=range(10))
#或者簡寫爲:
pool.map(run,range(10))
4. map_async 同理這個是map函數以異步非阻塞的形式
apply_async主要是將參數逐個的加入到進程中,平常經常會用到這個,因爲這種方式方便實現一些邏輯代碼,下來來個完整的代碼:
#coding:utf-8
import time
from multiprocessing import Pool
#執行方法
def run(n):
time.sleep(1)
print("我是方法:{}".format(n))
#注意:這裏的進程池pool對象定義一定要放在main主模塊下
if __name__ == '__main__':
#定義進程池
pool = Pool(processes=4)
for i in range(10):
pool.apply_async(func=run, args=(i,))
#簡寫: pool.apply_async(run, (i,))
pool.close() #關閉進程池,不在讓往進程池中添加進程
pool.join() #等待進程池中的所有進程執行完畢,必須在close()之後調用
好了,到這裏,進程池的基本用法就這樣了,這樣就通過多進程實現了多核任務,儘量利用計算機的性能資源。後面有興趣的同學還可以自己去了解下多線程與多進程的區別,還有就是協程的用法及優缺點,在這裏我就不再過多的講述了。
認真的時間總是過得這麼快,趕緊動手操作一下看看結果吧!
江湖不說再見,咱們下篇見!
關注公衆號,一起來提高自己吧!