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