知識點一:進程的理論
進程:正在進行的一個程序或者說一個任務,而負責執行任務的則是CPU
進程運行的的三種狀態:
1.運行:(由CPU來執行,越多越好,可提高效率)
2.阻塞:(遇到了IQ,3個里面可以通過減少阻塞有效的來提高效率)
3.就緒:(等待CPU來執行的過程)
知識點二:開啟進程的兩種方式
開啟進程:開啟進程就是將父進程里面串行執行的程序放到子進程里,實現並發執行,這個過程中,會將父進程數據拷貝一份到子進程。
運行角度:是2個進程
注意:子進程內的初始數據與父進程的一樣,如果子進程被創建了被運行了,那么
子進程里面數據更改對父進程無影響,2個進程是存在運行的
方式一:通過調用multiprocessing模塊下面的Process類方法
#方式一:通過調用multiprocessing模塊下面的Process類方法 ''' p = Process(target=task, args=('子進程',)) : target=task:指定執行任務的目標是誰 args:后面跟元組,是給target指定函數傳的參數 p=Process(..)相當於是對類Process進行實例化得到了P對象 ''' from multiprocessing import Process import time def task(x): print("%s is runnin"%x) #子進程打印輸出 time.sleep(3) print('%s is done'%x) #子進程打印輸出 if __name__ == '__main__': #開進程要統一放到main方法的下面 p=Process(target=task,args=('子進程',)) p.start() print('主') #父進程的打印輸出 ''' 注意點: 1.p=Process(target=task,args=('子進程',)) 這一步:只是在向操作系統發我要開啟一個子進程的信號(具體開子進程的操作是由操作系統來完成的) *所有這個過程中的時間也是不固定的 2.p.start(): 開啟一個子進程 運行過程分析: 右鍵運行父類先運行起來(此時p.start()子類也已經在造了,但是會有時間延遲)-->print('主')--> 然后依次運行子進程里面內容;子進程 is runnin\子進程 is done '''
方式二:借助process類,自定義一個類(繼承Process),從而造一個對象
#方式二:借助process類,自定義一個類(繼承Process),從而造一個對象 from multiprocessing import Process import time class Myprocess(Process): #輔助理解, # def __init__(self,x): # super().__init__()#保留原有Process類里面的方法 # self.name=x #***如果要自定義傳參,self.name=x必須要放到super()._init_()下面 # def run(self): print("%s is running" % self.name) #默認函數對象有name方法 ,結果為:Myprocess-1 time.sleep(3) print('%s is done' % self.name) if __name__ == '__main__': # p=Myprocess('子進程1',) 開啟init方式就可以自定義參數傳值 p=Myprocess() #實例化Myprocess類調用了類面的init方法,得到了一個對象p p1=Myprocess() p.start() #p.run() 對象去調用了類里面的run方法,進而執行run里面的函數體代碼 p1.start() print('主')
以上2中方式的對比分析:
方式二:子類只能運行同一個run里面輸出的方式(run名字是固定的,不能更改)
方式一:可以自定義多個task函數,並且寫不同的輸出內容,例如task1-->p1 task2-->p2...等等靈活性更高
父類、子類進程內存空間是彼此隔離的:
from multiprocessing import Process import time x=100 def task(): global x x=11 #當子類已經建立成功時,子類里面對數據的變動,不會印象父類 print(x) #11 print('done') if __name__ == '__main__': p=Process(target=task) p.start() time.sleep(10) # 讓父進程在原地等待10,是為了等父類先建立好,用於驗證子類里面的變動不會影響父類的值 print(x) #打印時父類的,即全局的 100
知識點三:僵屍進程、孤兒進程
僵屍進程:(無害的)
子進程運行結束后,會保留進程的ID號等信息,
目的是為了父進程能查看子進程的狀態,以及回收僵屍狀態的子進程
孤兒進程:(無害的)
在子類沒有運行完的情況下,父類先行結束,這種情況下,當子進程結束時,
狀態就叫做孤兒進程,當然也會被系統層面上的孤兒院回收
有一種情況是有害的:
如果父類,不停的在造子類,父類一直不死,此時PID會占用過多,導致內存也會占用很多
這種情況是有害的
知識點四:進程對象相關的屬性
1.PID接口查看
#查看PID應用: # print(p.pid):外面直接查看子類pid #os.getpid():在內部查看子類pid #os.getpid():在外面查看父類的pid #os.getppid():在里面查看父類的pid import time import os from multiprocessing import Process def task(x): print('%s is running'%os.getpid()) #子進程內查看自己pid的方式 time.sleep(100) print('子類下查看父類的id:%s'%os.getppid()) #查看父類的pid time.sleep(100) print('%s is done'%x) if __name__ == '__main__': p=Process(target=task,args=('子進程1',)) p.start() print(p.pid,) #父進程內查看子類pid的方式 time.sleep(50) print('父類下查看父類自己的id:',os.getpid()) print('主')
2.join()
import time from multiprocessing import Process def task(name,n): print('%s is running'%name) time.sleep(n) print('%s is done'%name) if __name__ == '__main__': p1=Process(target=task,args=("進程1",1)) #用時1s p2=Process(target=task,args=("進程2",2)) #用時1s p3=Process(target=task,args=("進程3",3)) #用時1s start_time=time.time() p1.start() # p1.join() #如果是這種情況就是總共6s左右了 p2.start() # p2.join() p3.start() # p3.join() # 讓父進程在原地等待,等子進程在運行完畢后,才執行下一行代碼() #注意:並不是串行,當第一秒在運行p1時,其實p2、p3也已經在運行,當1s后到p2時只需要再運行1s就到p3了,到p3也是一樣。 p1.join() p2.join() p3.join() stop_time=time.time() #3.2848567962646484總結 print(stop_time-start_time) print('主')