目錄python
# 第一種方式 from multiprocessing import Process import time def task(name): print(f'{name} is running') time.sleep(2) print(f'{name} is gone') if __name__ == '__main__': # 在Windows環境下,必須在main下開啓子進程 p = Process(target=task, args=('meet',)) # args元組形式 建立一個進程對象 p.start() print("===主進程") """ 結果: ===主進程 meet is running meet is done """ # p.start():開啓子進程的命令,通知操做系統在內存中開闢一個進程空間,將主進程的數據copy加載到子進程空間中,而後操做系統調用cpu去執行子進程。 開銷較大,所以會先執行主進程的代碼。
# 第二種方式 from multiprocessing import Process import time class MyProcess(Process): def __init__(self, name): super().__init__() # 重構父類的方法 self.name = name def run(self): # 必須寫run() print(f'{self.name} is running') time.sleep(2) print(f"{self.name} is gone") if __name__ == '__main__': p = MyProcess('meet') # 默認執行run() p.start() # 開啓子進程的命令 print("===主進程")
進程在內存中的惟一標識。linux
終端命令: tasklist # 查看計算機當前全部進程的pid面試
終端命令: tasklist|findstr pycharm # 查看pycharm的pidapp
代碼 :異步
import os print(os.getpid()) # 查看當前進程的pid print(os.getppid()) # 查看父進程的pid
from multiprocessing import Process lst = [1, 2] def task(): lst.append(3) print(f'子進程的:{lst}') if __name__ == '__main__': p = Process(target=task) p.start() print(f'主進程的:{lst}') """ 主進程的:[1, 2] 子進程的:[1, 2, 3] """ # 主進程與子進程之間存在空間隔離。
join :讓主進程等待子進程結束以後,再執行主進程。(讓主進程阻塞)
from multiprocessing import Process import time def task(sec): print('is running') time.sleep(sec) print('is gone') if __name__ == '__main__': start_time = time.time() p1 = Process(target=task, args=(1,)) p2 = Process(target=task, args=(2,)) p3 = Process(target=task, args=(3,)) p1.start() p2.start() p3.start() # 同時開啓 p1.join() print(f'p1時間:{time.time()-start_time}') # 1s多 p2.join() print(f'p2時間:{time.time()-start_time}') # 2s多 p3.join() print(f'p3時間:{time.time()-start_time}') # 3s多
from multiprocessing import Process import time def task(sec): print('is running') time.sleep(sec) print('is gone') if __name__ == '__main__': start_time = time.time() p1 = Process(target=task, args=(3,)) p2 = Process(target=task, args=(2,)) p3 = Process(target=task, args=(1,)) # 改變時間 p1.start() p2.start() p3.start() # 同時開啓 p1.join() print(f'p1時間:{time.time()-start_time}') # 3s多 #阻塞 p2.join() print(f'p2時間:{time.time()-start_time}') # 3s多 p3.join() print(f'p3時間:{time.time()-start_time}') # 3s多
# 面試題:將下面代碼優化 from multiprocessing import Process import time def task(sec): print('is running') time.sleep(sec) print('is gone') if __name__ == '__main__': start_time = time.time() p1 = Process(target=task, args=(1,)) p2 = Process(target=task, args=(2,)) p3 = Process(target=task, args=(3,)) p1.start() p2.start() p3.start() p1.join() p2.join() p3.join() print(f'運行時間:{time.time()-start_time}') # 3s多 # 上面代碼優化: lst = [] for i in range(1,4): p = Process(target=task, args=(i,)) lst.append(p) p.start() for i in lst: i.join() print(f'運行時間:{time.time()-start_time}') # 錯誤的優化: for i in range(1,4) p = Process(target=task, args=(i,)) p.start() p.join() print(f'運行時間:{time.time()-start_time}')
p.terminate() # 結束子進程 p.is_alive() # 判斷子進程是否活着 True/False p = Process(target=task, args=('meet',), age=18) # 給子進程對象添加一個age屬性。 print(p.age) # 18
實際中,主進程只有等待子進程結束後,主進程才結束。優化
基於Unix環境(linux,macOS):操作系統
主進程時刻監測子進程的運行狀態,當子進程結束後,一段時間內,纔會將子進程回收。code
爲何不立刻回收?對象
Unix針對上面的問題,提供了一種機制:進程
全部的子進程結束後,立馬釋放掉文件的操做連接、內存等的大部分數據,可是會保留一些內容:進程號、結束時間、運行狀態,等待子進程監測、回收。
殭屍進程:子進程在結束後,主進程並無調用wait或waitpid獲取子進程的狀態信息,子進程仍然保留了一些描述內容,這種進程被稱爲殭屍進程。
危害:若是父進程不對殭屍進程進行回收(wait/waitpid),產生大量的殭屍進程,這樣會佔用內存,佔用進程的pid號。
父進程因爲某種緣由結束,但子進程還在運行中,則稱這些子進程爲孤兒進程。
回收機制:Unix中孤兒進程會被 init 進程回收,init 變成父進程。
殭屍進程解決方法:
直接殺死父進程。將全部殭屍進程變成孤兒進程,由 init進程回收。
# 子進程守護着主進程,只要主進程結束,子進程也跟着結束。 from multiprocessing import Process import time def task(name): print(f'{name} is running') time.sleep(2) print(f'{name} is gone') if __name__ == '__main__': p = Process(target=task, args=('meet',)) # 建立一個進程對象 p.daemon = True # 放在start前,不然會報錯。 p.start() time.sleep(1) print("===主進程") """ meet is running ===主進程 """