一、并發與并行的差別
- 并發:一個時間段内,有幾個程式在同一個CPU上運作,但是任意時刻隻有一個程式在CPU上運作。
- 并行:并行是指任意時刻上,有多個程式同時運作在多個CPU上所有常說高并發,沒有說高并行,因為CPU數量是有限的。
二、多程序與多線程的差別
- 對于耗 CPU 的操作,用多程序優于多線程,因為有 GIL 鎖,不會常釋放,耗 CPU 操作無法使用多線程。
- 多 IO 操作,常會釋放 GIL,是以可以多使用多線程。
三、多程序程式設計
1. 使用 fork() 方法建立子程序(fork隻能用于linux/unix中)。
import os
# fork隻能用于linux/unix中
pid = os.fork()
print("bobby")
if pid == 0: # 子程序運作這段
print('子程序 {} ,父程序是: {}.' .format(os.getpid(), os.getppid()))
else: # 父程序運作這段
print('我是父程序:{}.'.format(pid))
"""
在 linux 下運作後,會列印:
bobby
我是父程序: 24474
bobby
子程序 24474, 父程序是:24473
"""
fork() 方法建立一個子程序,子程序會将父程序裡的資料、代碼原樣拷貝到子程序當中,父程序依然會向下運作,父子程序都從 fork() 的地方繼向下運作。
2. 使用 ProcessPoolExecutor 進行多程序程式設計。
from concurrent.futures import ProcessPoolExecutor
ProcessPoolExecutor 接口跟 ThreadPoolExecutor 的 api 幾乎一模一樣,具體使用方法可以參照上一篇部落格:python線程池 ThreadPoolExecutor 使用詳解
3. 使用 multiprocessing 子產品進行多程序程式設計。
(1)multiprocessing.Process
import multiprocessing as mp
threads = []
for i in path:
threads.append(mp.Process(target=md5sum,args=(i,)))
#建立一個multiprocessing.process.Process對象
#執行
for m in threads:
m.start()
#回收
for m in threads:
m.join()
(2)使用線程池 multiprocessing.Pool()
def test():
pass
# 建立一個multiprocessing.pool.Pool的對象
p1 = mp.Pool(processes =5)
#向程序池裡添加任務
result = pool.apply_async(test, args=(3,))
# 關閉程序池,阻止更多的任務送出到程序池Pool,待任務完成後,工作程序會退出
p1.close()
# 結束工作程序,不再處理未完成的任務
# p.terminate()
# 等待工作線程的退出,必須在close()或terminate()之後使用,因被終止的程序需要被父程序調用wait(join等價于wait),否則程序會成為僵屍程序。
p1.join()
print(result.get())
(a) Pool裡有兩種添加子程序的方法:
- apply_async 異步添加
- p1.apply(test) 阻塞式添加,逐漸執行,相當于單程序
(b) 當Pool所有的程序任務完成後,會産生5個僵屍程序,如果主線程不結束,系統不會自動回收資源,需要調用join函數去回收。
(c) map() 方法:它融合了map函數和apply_async()函數的功能
(d) p.close():關閉程序池,阻止更多的任務送出到程序池Pool,待任務完成後,工作程序會退出
(e) p.terminate():結束工作程序,不再處理未完成的任務
(f) p.join():等待工作線程的退出,必須在close()或terminate()之後使用,因被終止的程序需要被父程序調用wait(join等價于wait),否則程序會成為僵屍程序。
參考文章: [Python]multiprocessing