進程
- 概念:指的時運行的程序以及運行時用到的資源這個整體稱之爲進程
經典三狀態:
- 就緒態:運行的條件都已經慢去,正在等待cpu執行(cpu分配時間片執行,切換到執行態)
- 執行態:cpu正在執行其功能(時間片用完就切換到就緒態)
- 等待態:在運行的代碼中有需要等待某些條件(數據input()、時間sleep())阻塞等待,如果條件滿足,切換到就緒態
創建進程:
pro = multiprocessing.Process(target= 函數名, args=(參數列表元組))
pro.start()
主進程阻塞等待子進程退出
pro.join(time) 表示主進程最多等子進程time秒
pro.is_alilve() 判斷子進程是否存活
pro.terminate() 直接終止子進程(信號有延時)-->.join()
pid:當前進程的進程號(ps aux,ps -eflgrep)
getpid()子進程的pid,getppid() 子進程的父進程的pid
進程間是獨立的地址空間,所以不共享全局變量
進程間通信Queue
創建隊列
q = multiprocessing.Queue(參數表示隊列最大長度)
q.put() 存放數據
q.get() 取出數據
q.full() 判斷是否滿了
q.empty() 判斷是否空了
q.qsize() 獲取隊列長度
進程池Pool
創建進程池
p = multiprocessing.Pool(參數表示進程的最大數量)
# 添加任務
p.apply 是阻塞添加任務,會等待添加的任務執行完成纔會繼續往下執行
p.apply_async 非阻塞的任務添加,只管添加任務,不等任務結束
# 關閉進程池
p.close()
p.terminate() 強制終止進程池中所有的正在執行的進程任務
# 等待所有任務執行完成
p.join() 保持主進程存活,等待所有子進程完成
注意事項
- 如果需要在進程池中使用進程間通信Queue,不要使用multiprocessing.Queue()(要求是通過繼承的方式創建的進程),應該使用multiprocessing.Manager.Queue()
- .close() .terminate()之後一般都建議更上 .join(); .join()之前一定要調用 .close() .terminate()
進程與線程的對比
定義的不同
進程是系統進行資源分配和調度的一個獨立單位
線程是進程的一個實體,是CPU調度和分派的基本單位,它是比進程更小的能獨立運行的基本單位,線程自己基本上不擁有系統資源,只擁有一點在運行中必不可少的資源(如程序計數器,一組寄存器和棧),但是它可與同屬一個進程的其他線程共享進程所擁有的全部資源
區別
- 一個程序至少有一個進程,一個進程至少有一個線程
- 線程的劃分尺度小於進程(資源比進度少),使得多線程程序的併發性高
- 進程在執行過程中擁有獨立的內存單元,而多個線程共享內存,從而極大的提高了程序的運行效率
- 線程不能獨立執行,必須依存在進程中
- 可以將進程理解爲工廠中的一條流水線,而其中的線程就是這個流水線上的工人
優缺點
進程和線程在使用上各有優缺點,線程執行開銷小,但不利於資源的管理個保護;而進程相反
進程簡單的實現文件夾copy器
import os
import time
import multiprocessing
def copy_file(src_path, dest_path, file_name, q):
"""拷貝文件的函數"""
f = open(src_path + "/" + file_name, "rb")
f1 = open(dest_path + "/" + file_name, "wb")
f1.write(f.read())
f.close()
f1.close()
# 將文件名加入隊列
q.put(file_name)
if __name__ == '__main__':
# 使用多進程 完成對指定目錄下的文件拷貝
# 1.用戶輸入目錄-->源目錄
src_path = input("輸入你要拷貝的文件名稱:")
# 2.創建一個新的目錄 存放拷貝之後的文件數據
dest_path = src_path + "[復件]"
os.mkdir(dest_path)
# 3.獲取指定目錄下的所有文件信息
file_list = os.listdir(src_path)
# 子進程再複製完成文件之後 將文件名寫入隊列 父進程從隊列中取出已經完成的文件列表
q = multiprocessing.Queue()
# 4.傳入 源目錄 目的目錄 文件名 使用一個子進程完成該文件的拷貝
for file in file_list:
pro = multiprocessing.Process(target=copy_file, args=(src_path, dest_path, file, q))
pro.start()
# 顯示拷貝進度模塊
count = 0
while True:
file_name = q.get()
count += 1
print("\r 當前的進度%.2f %%" % ((count / len(file_list)) * 100), end="")
time.sleep(0.6)
if count == len(file_list):
print("拷貝完成")
break
# 進程小坑
import multiprocessing
def write():
print("11")
print("123456")
if __name__ == '__main__':
pro1 = multiprocessing.Process(target=write)
pro1.start()
-----運行結果-----
123456
123456
11