多任务--线程
進程
一、概念
二、進程的創建和操作
三、進程通信--Queue
四、進程池
五、進程與線程區別
六、案例
回到頂部
?
一、概念
1.概念
進程:?通俗理解一個運行的程序或者軟件,進程是操作系統資源分配的基本單位。
注意:?一個程序至少有一個進程,一個進程至少有一個線程,多進程可以完成多任務.
2.進程的執行狀態
工作中,任務數往往大于cpu的核數,即一定有一些任務正在執行,而另外一些任務在等待cpu進行執行,因此導致了有了不同的狀態
?
- 就緒態:運行的條件都已經慢去,正在等在cpu執行
- 執行態:cpu正在執行其功能
- 等待態:等待某些條件滿足,例如一個程序sleep了,此時就處于等待態
二、進程的創建和操作
1.進程的創建
創建進程 :?
開始執行 : pro.start()
2.進程的操作
? ? ?pro.join(2) 阻塞等待子進程2秒 如果子進程沒有終止那主進程就直接往下執行
? pro.terminate()?? 終止子進程
? pro.is_alive() 判斷子進程狀態
#!/usr/bin/env python # _*_ coding:utf-8 _*_ # Author:Mr.yang import multiprocessing import time import osdef pro_info(info, data):"""子進程 運行的代碼"""for i in range(30):print("這是子進程 info=%s data=%s PID=%s PPID=%s" % (info,data,os.getpid(),os.getppid()))time.sleep(1)def main():"""單進程 單線程模式 主進程"""# 創建子進程pro = multiprocessing.Process(target=pro_info, args=("今天天氣不錯",), kwargs={"data":"50"}, name="陳特特")# 創建 啟動子進程 pro.start()# 主進程阻塞等待子進程 2秒 / 如果能等到子進程退出 回收子進程的資源pro.join(2)print("獲取子進程的pid = %s name = %s" % (pro.pid,pro.name))print("===============================")# 判斷子進程是否存活print(pro.is_alive())# # 終止子進程 像操作系統發出一個 終止子進程的信號 存在延遲 不要立即判斷子進程的狀態# pro.terminate()# 判斷子進程是否存活print(pro.is_alive())print("===============================")for i in range(3):# 查看當前所在進程的PIDprint("這是主進程 PID=%s" % os.getpid())time.sleep(1)if __name__ == '__main__':main() 示例代碼三、進程通信--Queue
1.使用隊列Queue的原因
原因: 進程間不共享全局資源
Queue 是一種進程間通信的方式, 先進先出
2.使用方法
- 創建 隊列對象 = multiprocessing.Queue(長度)
- 放 隊列對象.put(數據)
- 取 數據 = 隊列對象.get()
- 判斷空 隊列對象.empty()
- 判斷滿 隊列對象.full()
- 數量 隊列對象.qsize() import multiprocessing import timedef proc_func(q):"""子進程入口"""while True:time.sleep(3)# 判斷空if q.empty():print("隊列中已經沒有了 稍后再來")time.sleep(3)# 從隊列中取出數據data = q.get()print("從隊列中取出了數據%s" % data)def main():pass# 1 創建出來 主進程和子進程通信所需的 隊列對象q = multiprocessing.Queue(3)# 2 創建子進程 pro = multiprocessing.Process(target=proc_func, args=(q,))pro.start()while True:# 3 接收輸入 放入隊列中data = input(":")# 判斷隊列滿 if q.full():print("慢點輸入已經滿了 馬上溢出了")time.sleep(1)# 向隊列中放入數據 q.put(data)if __name__ == '__main__':main() 示例
四、進程池
1.工作模式
模式 :?重復利用已經空閑的進程執行 多任務
優點 : ?提高任務的響應速度
2.添加任務兩種方式
會阻塞等待添加任務的執行完成后才會繼續往下執行
? 異步方式 :只添加任務 不會等待任務執行完成
3.使用步驟和注意事項?
1 創建進程池 進程池對象 = multiprocessing.Pool(工作進程的數量) 2 添加任務 同步 進程池對象.apply(入口) 添加任務并等待任務執行完成異步 進程池對象.apply_async(入口) 只添加任務 不等待任務完成3 關閉進程池進程池對象.close() 不允許添加新任務4 等待所有任務執行完成進程池對象.join()注意:
五、進程與線程區別
1.區別
- 進程之間不共享全局變量
- 線程之間共享全局變量,但是要注意資源競爭的問題,解決辦法: 互斥鎖或者線程同步
- 創建進程的資源開銷要比創建線程的資源開銷要大
- 進程是操作系統資源分配的基本單位,線程是CPU調度的基本單位
- 線程不能夠獨立執行,必須依存在進程中
- 多進程開發比單進程多線程開發穩定性要強
2.優缺點
多進程:
-
-
- 優點:可以用多核
- 缺點:資源開銷大
-
多線程:
-
-
- 優點:資源開銷小
- 缺點:不能使用多核
-
3.功能對比
-
- 進程,能夠完成多任務,比如 在一臺電腦上能夠同時運行多個QQ
- 線程,能夠完成多任務,比如 一個QQ中的多個聊天窗口
4.定義對比
-
- 進程是系統進行資源分配基本單位,每啟動一個進程操作系統都需要為其分配運行資源。
- 線程是運行程序中的一個執行分支,是CPU調度基本單位。
- 總結:進程是操作系統資源分配的基本單位,線程是CPU調度的基本單位
?
六、案例
#!/usr/bin/env python # _*_ coding:utf-8 _*_ # Author:Mr.yang import multiprocessing import osdef copy_file(src_path, dest_path, file):"""從源目錄下 將file對應的文件數據讀取并且寫到目的目錄下 file文件中"""# 1.打開源目錄下的文件用以讀src_file = open(src_path + "/" + file, "rb")print(dest_path + "/" + file)# 2.打目的目錄下的文件用以寫dest_file = open(dest_path + "/" + file, "wb")# 3.一遍從源文件中讀取數據 寫入目的文件中while True:file_data = src_file.read(1024)if not file_data:print("%s文件拷貝完成" % file)breakdest_file.write(file_data)# 4.完成后 關閉源文件 關閉目的文件中 src_file.close()dest_file.close()def main():# 1.用戶輸入備份的目錄source_path = input("請輸入要備份的目錄:")# 2.根據源目錄創建一個目的目錄 源目錄-備份dest_path = source_path + "-備份"os.mkdir(dest_path)# 3.根據源目錄去獲取源目錄下所有的 文件名稱file_list = os.listdir(source_path)# print(file_list)# 4.根據每個源文件的名稱 讀取出每個文件的數據 將數據寫入到 目的目錄/源文件for file in file_list:pro = multiprocessing.Process(target=copy_file, args=(source_path, dest_path, file))pro.start()if __name__ == '__main__':main() 備份當前目錄---多進程 #!/usr/bin/env python # _*_ coding:utf-8 _*_ # Author:Mr.yang import multiprocessing import time import osdef copy_file(src_path, dest_path, file, q):"""從源目錄下 將file對應的文件數據讀取并且寫到目的目錄下 file文件中"""# 1.打開源目錄下的文件用以讀src_file = open(src_path + "/" + file, "rb")# 2.打目的目錄下的文件用以寫dest_file = open(dest_path + "/" + file, "wb")# 3.一遍從源文件中讀取數據 寫入目的文件中while True:file_data = src_file.read(1024)if not file_data:# print("%s文件拷貝完成" % file)breakdest_file.write(file_data)# 4.完成后 關閉源文件 關閉目的文件中 src_file.close()dest_file.close()# 5.當任務完成后 向隊列中添加一個消息 表示完成 q.put(file)def main():# 1.用戶輸入備份的目錄source_path = input("請輸入要備份的目錄:")# 2.根據源目錄創建一個目的目錄 源目錄-備份dest_path = source_path + "-備份"os.mkdir(dest_path)# 3.根據源目錄去獲取源目錄下所有的 文件名稱file_list = os.listdir(source_path)# print(file_list)# 4.根據每個源文件的名稱 讀取出每個文件的數據 將數據寫入到 目的目錄/源文件# 使用進程池處理每個任務# 4.0 創建出一個隊列 用于進程間通信 不能使用multiprocessing.Queue(10)# q = multiprocessing.Queue(10)q = multiprocessing.Manager().Queue(10)# 4.1 創建進程池p = multiprocessing.Pool(4)# 4.2 添加任務到進程池中for file in file_list:p.apply_async(copy_file,args=(source_path, dest_path, file, q))# 4.3 關閉進程池 p.close()# 從隊列中取出消息count = 0while True:if count == len(file_list):breakq.get()count += 1print("\r當前進度是%.2f %%" % ((count/len(file_list))*100), end="")time.sleep(0.1)# 4.4 等待進程池所有任務都執行完成 p.join()if __name__ == '__main__':main() 備份當前目錄---進程池?
轉載于:https://www.cnblogs.com/Mryang123/p/9997738.html
總結
- 上一篇: javaScript年份下拉列表框内容为
- 下一篇: Jobs(三) HTML的form表单提