1. 多進(jìn)程
程序:program是一個指令的集合
進(jìn)程:process,正在執(zhí)行中的程序,是一個靜態(tài)的概念
1) 進(jìn)程是程序的一次靜態(tài)執(zhí)行過程,占用特定的地址空間
2) 每個進(jìn)程都是獨(dú)立的,由3部分組成cpu,data,code
3) 缺點(diǎn):內(nèi)存的浪費(fèi),cpu的負(fù)擔(dān)
4) 數(shù)據(jù)區(qū)、代碼區(qū)、堆、棧
操作系統(tǒng)輪流讓各個任務(wù)交替執(zhí)行,由于CPU的執(zhí)行速度實(shí)在是太快了,我們感覺就像所有任務(wù)都在同時執(zhí)行一樣
真正的并行執(zhí)行多任務(wù)只能在多核心CPU上實(shí)現(xiàn),但是,由于任務(wù)數(shù)據(jù)遠(yuǎn)遠(yuǎn)多于CPU的核心數(shù)量,所以,操作系統(tǒng)也會自動把很多任務(wù)輪流調(diào)度到每個核心上執(zhí)行
在unix/linux操作系統(tǒng)中,提供了一個fork()系統(tǒng)函數(shù),它非常特殊
1) 普通的函數(shù)調(diào)用,調(diào)用一次,返回一次,但是fork()調(diào)用一次,返回兩次,因?yàn)椴僮飨到y(tǒng)自動把當(dāng)前進(jìn)程(稱為父進(jìn)程)復(fù)制了一份(稱為子進(jìn)程),然后,分別在父進(jìn)程和子進(jìn)程內(nèi)返回
2) 子進(jìn)程永遠(yuǎn)返回0,而父進(jìn)程返回子進(jìn)程的ID
3) 一個父進(jìn)程可以fork出很多子進(jìn)程,所以,父進(jìn)程要記下每個子進(jìn)程 的ID,而子進(jìn)程中需要調(diào)用getppid()就可以拿到父進(jìn)程的id
4) 父進(jìn)程、子進(jìn)程執(zhí)行順序沒有規(guī)律,完全取決于操作系統(tǒng)的調(diào)度算法

進(jìn)程擁有獨(dú)立的運(yùn)行空間,變量的值不能共享


由于python是跨平臺的,自然也應(yīng)該提供一個跨平臺的多進(jìn)程支持。multiprocessing模塊就是跨平臺版本的多進(jìn)程模塊
multiprocessing模塊提供了一個process類來代表一個進(jìn)程對象

創(chuàng)建子進(jìn)程時,只需要傳入一個執(zhí)行函數(shù)和函數(shù)的參數(shù),創(chuàng)建一個Process實(shí)例,用start()方法啟動,這樣創(chuàng)建進(jìn)程比fork()還要簡單
Process([group [,target [,name [,args [,kwargs]]]]])
target | 表示這個進(jìn)程實(shí)例所調(diào)用對象 |
args | 表示調(diào)用對象的位置參數(shù),元組 |
kwargs | 表示調(diào)用對象的關(guān)鍵字參數(shù),字典 |
name | 為當(dāng)前進(jìn)程實(shí)例的別名 |
group | 創(chuàng)建一個進(jìn)程組,大多數(shù)情況下用不到 |
Process類常用方法 |
join()方法 | 可以等待子進(jìn)程結(jié)束后再繼續(xù)往下運(yùn)行,通常用于進(jìn)程間的同步 |
is_alive() | 判斷進(jìn)程實(shí)例是否還在執(zhí)行 |
join([timeout]) | 是否等待進(jìn)程實(shí)例執(zhí)行結(jié)束,或等待多少秒 |
start() | 啟動進(jìn)程實(shí)例(創(chuàng)建子進(jìn)程) |
run() | 如果沒有給定target參數(shù),對這個對象調(diào)用start()方法時,就將執(zhí)行對象中的run()方法 |
terminate() | 不管任務(wù)是否完成,立即終止 |
Process類常用屬性 |
name | 當(dāng)前進(jìn)程實(shí)例別名,默認(rèn)為Process-N,N為從1開始遞增的整數(shù) |
pid | 當(dāng)前進(jìn)程實(shí)例的pid值 |
例1

例2

創(chuàng)建新的的進(jìn)程還能夠使用類的方式,可以自定義一個類,繼承Process類,每次實(shí)例化這個類的的時候,就等同于實(shí)例化一個進(jìn)程對象

例,創(chuàng)建多個進(jìn)程

multiprocessing的Pool方法
當(dāng)需要創(chuàng)建的子進(jìn)程數(shù)量不多時,可以直接利用multiprocessing中的Process動態(tài)生成多個進(jìn)程,但如果是上百甚至上千個目標(biāo),手動去創(chuàng)建進(jìn)程進(jìn)程的工作量巨大,此時就可可以用到到multiprocessing模塊提供的Pool方法
初始化Pool時,可以指定一個最大進(jìn)程數(shù),當(dāng)有有新的請求提交到Pool時,如果池還沒滿,那么就會創(chuàng)建一一個新的進(jìn)程用來執(zhí)行該請求,但如果池中的進(jìn)程數(shù)已經(jīng)達(dá)到到指定的最大值,那么該請求就會會等待,直到池中有進(jìn)程結(jié)束,才會創(chuàng)建新的進(jìn)程來執(zhí)行。
multiprocessing.Pool常用函數(shù)解析
apply_async(func[,args[,kwds]]):使用非阻塞阻塞方式調(diào)用func(并行執(zhí)行,堵塞方式必須等待上一個進(jìn)程退出才能執(zhí)行下一個進(jìn)程進(jìn)程),args為傳遞給func的參數(shù)列表,kwds為傳遞給func的關(guān)鍵字參數(shù)參數(shù)列表;
apply(func[,args[,kwds]]):使用阻塞方式調(diào)用func
close():關(guān)閉Pool,使其不再接受新的任務(wù)。不是馬上關(guān),執(zhí)行中的任務(wù)仍會執(zhí)行。
terminate():不管任務(wù)是否完成,立即終止
join():主進(jìn)程阻塞,等待子進(jìn)程的退出,必須在colse或terminate之后使用
例,

| 
|
異步,非阻塞 | 同步,阻塞 |
消息隊(duì)列
操作系統(tǒng)提供了很多機(jī)制來實(shí)現(xiàn)進(jìn)程間的通信 ,multiprocessing模塊就提供了Queue和Pipe兩種方法來實(shí)現(xiàn)
Queue模塊專門實(shí)現(xiàn)消息隊(duì)列Queue對象。
queue只有maxsize一個構(gòu)造參數(shù),用來指定隊(duì)列容量,指定為0的時候代表容量無限。
主要有以下成員函數(shù):
Queue.qsize():返回消息隊(duì)列的當(dāng)前空間。返回的值不一定可靠。
Queue.empty():判斷消息隊(duì)列是否為空,返回True或False。同樣不可靠。
Queue.full():類似上邊,判斷消息隊(duì)列是否滿
Queue.put(item, block=True, timeout=None):往消息隊(duì)列中存放消息。block可以控制是否阻塞,timeout指定阻塞時候的等待時間。如果不阻塞或者超時,會引起一個full exception。
Queue.put_nowait(item):相當(dāng)于put(item, False).Queue.get(block=True, timeout=None):獲取一個消息,其他同put。