程序
程序:編寫完的代碼稱為程序。
進程
進程:又稱重量級進程,正在執行中的程序稱為進程。進程的執行會占用內存等資源。多個進程同時執行時,每個進程的執行都需要由操作系統按一定的算法(RR調度、優先數調度算法等)分配內存空間。
並行與並發
並行:在多核系統中,每個cpu執行一個進程,可以理解為cpu的數大於進程數,所有進程同時進行。
並發:在操作系統中同時執行多個進程,可以理解為cpu的數小於進程數,有些進程會沒有機會執行。
並發與並行的區別:並行指兩個或多個程序在同一時刻執行;並發指兩個或多個程序在同一時間間隔內發生,可以理解為在表面上看是同時進行,但在同一時刻只有少於程序的總數的程序在執行,計算機利用自己的調度算法讓這些程序分時的交叉執行,由於交換的時間非常短暫,宏觀上就像是在同時進行一樣。
多進程
在python中,每一個運行的程序都有一個主進程,可以利用模塊中封裝的方法來創建子進程。
1、利用os模塊中的fork()來創建子進程
import os, time pid = os.fork() print("外面的pid",pid) if pid == 0: print("子進程中的程序") print("子進程的pid=", os.getpid()) print("父進程的pid=", os.getppid()) elif pid > 0: print("父進程中的程序") print("子進程的pid=", os.getpid()) print("父進程的pid=", os.getppid()) else : print("創建失敗")
解釋:
os.fork():os模塊中用來創建子進程的方法,當程序執行到os.fork()時,操作系統會將當前的進程復制一份,原來的進程稱為父進程,新創建的進程稱為子進程,兩個進程會各自互不干擾的執行下面的程序,父進程與子進程的執行順序與系統調度有關。父進程與子進程都會在os.fork()中得到一個返回值,子進程的返回值為0,父進程的返回值為子進程的進程號,這個值永遠大於零,具體數值由操作系統分配,如果返回值為負數則表明創建子進程失敗。
os.getpid():獲取進程的進程號。
os.getppid():獲取父進程的進程號。
注意:這個os.fork()方法只有在unix系統中才會有,在window下沒有。
2、利用multiprocessing模塊Process類創建進程
在multiprocessing模塊中提供一個Process()類來創建進程,直接上代碼:
from multiprocessing import Process import time def test(a): for i in range(a): print("子進程...") time.sleep(1) p = Process(target=test,args=(5,)) p.start() p.join(2) while True: print("父進程...") time.sleep(1)
解釋:
這里的p相當於Process類的一個實例對象,每實例化一個對象就是創建一個子進程。
target = test :子進程所執行的任務,就是test這個函數
args = (5,) :給進程函數傳參,這里需要用元祖的方式進行傳參
p.start() :執行子進程,只用調用start()方法,子進才會執行
p.join(n) :讓主進程等待n秒鍾
在進程結束后,主進程會等待子進程先結束,如果主進程先結束,那么所有的子進程都會結束。
Process常用的方法:
start():啟動進程
is_alive() :判斷進程是否還在執行,返回True 或 False
join(n) : 主進程等待子進程,n為等待的時間(秒)
run() :在調用start方法時會自動調用run()方法,可以創建Process類的子類來重寫run()方法的方式創建進程
terminate():使進程立即終止
3、利用Process類的子類來創建進程
from multiprocessing import Process import time class NewProcess(Process): def __init__(self,num): self.num = num super().__init__() def run(self): print("開始重寫run了") i = 0 while True: time.sleep(1) i += 1 print("子進程",i) if i == self.num: break p = NewProcess(6) p.start() p.join(2) while True: if p.is_alive(): print("父進程") time.sleep(1) elif not p.is_alive(): print("子進程結束了") break
這個方法核心就是創建一個Process類的子類,利用重寫run()方法來實現任務的添加。
4、利用multiprocessing模塊進程池Pool創建進程
Process類適合用於創建所需進程數量不多的情況,如果需要創建大量的進程,則需要利用進程池來創建進程。
from multiprocessing import Pool import time import os def work(i): time.sleep(1) print(i,"當前程序的pid=",os.getpid()) def work1(i): time.sleep(1) print(i,"當前程序的pid=",os.getpid()) def work2(i): time.sleep(1) print(i,"當前程序的pid=",os.getpid()) # 創建進程池 pool = Pool(2) # 使進程開始執行 pool.apply_async(work,(1,)) pool.apply_async(work1,(2,)) pool.apply_async(work2,(3,)) pool.apply(work1,(4,)) pool.apply(work2,(5,)) pool.apply(work1,(6,)) pool.apply(work2,(7,)) # 關閉進程池 pool.close() # 讓主進程等待子進程 pool.join()
解釋:
pool = Pool(2)為創建一個進程池,進程池中同時開兩個進程,如果任務多於進程數時,進程會逐個執行任務,當一個進程完成任務后,接着執行待完成的任務,直到所有任務全部完成。
pool.apply_async(func,args) :非堵塞式,異步執行。func調用的為任務,args:為func傳參,參數以元祖的方式傳遞。
pool.apply(func,args) :堵塞式執行。進程會等待上一個進程結束才會進行。傳參同上。
pool.close() :關閉進程池,停止向進程池中添加任務
pool.join() :使主進程等待。必須在close()或者terninate()后面使用。