您好,登錄后才能下訂單哦!
這篇文章主要講解了“Python的多線程多進程是什么”,文中的講解內容簡單清晰,易于學習與理解,下面請大家跟著小編的思路慢慢深入,一起來研究和學習“Python的多線程多進程是什么”吧!
我是參考 Github Python 100 天的文章寫的,再結合自己的小練習,總結
最近在面大廠,發現許多大廠都會問 Python 的多線程、多進程,所以我覺得很有必要總結學習下
操作系統中執行的一個程序,類似微信、QQ,每個程序都是一個進程
它是 CPU 最小資源分配單元
操作系統會給進程分配內存空間,每個進程都會有自己的地址空間、數據棧以及其他用于跟蹤進程執行的輔助數據
操作系統管理所有進程的執行,為它們合理的分配資源
進程可以通過 fork、spawn 的方式來創建新的進程來執行其他任務
不過新的進程有自己獨立的內存空間、數據棧
因此不同進程間需要通過通信機制(IPC)來實現數據共享
管道
信號
套接字
共享內存區
進程中可以擁有多個并發的執行線索
它是 CPU 最小調度的執行單元
同一個進程下的線程共享相同的上下文
相對于進程來說,線程間的信息共享和通信更加容易
真正的并發是不可能的
因為在某個時刻,CPU 只能運行唯一的一個線程
多個線程共享了 CPU 的執行時間
提升程序的性能和改善用戶體驗
今天日常使用的軟件幾乎都用到了多線程
站在其他進程的角度,多線程的程序對其他程序并不友好,因為它占用了更多的 CPU 執行時間,導致其他程序無法獲得足夠的 CPU 執行時間
編寫和調試多線程的程序對開發者要求較高
多進程
多線程
多進程+多線程
Linux 操作系統上提供了 fork() 系統調用來創建進程
調用 fork() 函數的是父進程
創建的是子進程
子進程是父進程的拷貝
但子進程有自己的 PID
fork() 函數非常特殊,它會返回兩次,父進程中調用 fork() 會返回子進程的 PID,子進程中調用 fork() 得到的都是0
os 模塊提供了 fork()
實現跨平臺的多進程變成,可以使用 multiprocessing 模塊的 Process 類來創建子進程
還提供了更高級的封裝,例如批量啟動進程的進程池 pool、用于進程間同喜你的隊列 Queue 和管道 Pipe
from random import randintfrom time import time, sleepdef download_task(filename):print('開始下載%s...' % filename) time_to_download = randint(5, 10) sleep(time_to_download)print('%s下載完成! 耗費了%d秒' % (filename, time_to_download))def main(): start = time() download_task('Python從入門到住院.pdf') download_task('Peking Hot.avi') end = time()print('總共耗費了%.2f秒.' % (end - start))if __name__ == '__main__': main()
開始下載Python從入門到住院.pdf... Python從入門到住院.pdf下載完成! 耗費了10秒 開始下載Peking Hot.avi... Peking Hot.avi下載完成! 耗費了9秒 總共耗費了19.02秒.
可以看到需要先等第一個文件下載完才能下載第二個文件,效率很低
from random import randintfrom time import time, sleepfrom multiprocessing import Processdef download_task(filename):print('開始下載%s...' % filename) time_to_download = randint(5, 10) sleep(time_to_download)print('%s下載完成! 耗費了%d秒' % (filename, time_to_download))def main2(): start = time() p1 = Process(target=download_task,args=("Python從入門到住院.pdf",)) p1.start() p2 = Process(target=download_task, args=("Peking Hot.avi",)) p2.start() p1.join() p2.join() end = time()print('總共耗費了%.2f秒.' % (end - start))if __name__ == '__main__': main2()
開始下載Python從入門到住院.pdf... 開始下載Peking Hot.avi... Python從入門到住院.pdf下載完成! 耗費了6秒 Peking Hot.avi下載完成! 耗費了10秒 總共耗費了10.17秒.
兩個任務同時執行,總耗時不再是兩個任務的時間總和
Process:通過 Process 類創建進程對象
target:通過 target 參數傳入一個函數名來表示進程啟動后要執行的代碼
args:是一個元組,代表傳遞給函數的參數列表
start:Process 的 start() 方法來啟動進程
join:Process 的 join() 方法表示等待進程執行結束,才會往下執行
推薦 threading 模塊來實現多線程編程,它提供了更好的面向對象封裝
#!/usr/bin/env python# -*- coding: utf-8 -*-"""__title__ = __Time__ = 2021/3/19 18:17 __Author__ = 小菠蘿測試筆記 __Blog__ = https://www.cnblogs.com/poloyy/"""from random import randintfrom threading import Threadfrom time import time, sleepdef download_task(filename):print('開始下載%s...' % filename) time_to_download = randint(5, 10) sleep(time_to_download)print('%s下載完成! 耗費了%d秒' % (filename, time_to_download))def main3(): start = time() p1 = Thread(target=download_task,args=("Python從入門到住院.pdf",)) p1.start() p2 = Process(target=download_task, args=("Peking Hot.avi",)) p2.start() p1.join() p2.join() end = time()print('總共耗費了%.2f秒.' % (end - start))if __name__ == '__main__': main3()
開始下載Python從入門到住院.pdf... 開始下載Peking Hot.avi... Peking Hot.avi下載完成! 耗費了6秒 Python從入門到住院.pdf下載完成! 耗費了8秒 總共耗費了8.01秒.
一樣執行效率高很多
#!/usr/bin/env python# -*- coding: utf-8 -*-"""__title__ = __Time__ = 2021/3/19 18:17 __Author__ = 小菠蘿測試筆記 __Blog__ = https://www.cnblogs.com/poloyy/"""from random import randintfrom threading import Threadfrom time import time, sleepclass downLoadTask(Thread):def __init__(self,filename): super().__init__() self.filename = filenamedef run(self) -> None:print('開始下載%s...' % self.filename) time_to_download = randint(5, 10) sleep(time_to_download)print('%s下載完成! 耗費了%d秒' % (self.filename, time_to_download))def main3(): start = time() p1 = downLoadTask("Python從入門到住院.pdf") p2 = downLoadTask("Peking Hot.avi") p1.start() p2.start() p1.join() p2.join() end = time()print('總共耗費了%.2f秒.' % (end - start))if __name__ == '__main__': main3()
開始下載Python從入門到住院.pdf... 開始下載Peking Hot.avi... Peking Hot.avi下載完成! 耗費了6秒 Python從入門到住院.pdf下載完成! 耗費了9秒 總共耗費了9.00秒.
也是一樣的高效運行
比較點 | start | run |
作用 | 啟動線程,獲取 CPU 時間片 | 運行線程指定的代碼塊 |
線程狀態 | 可運行狀態 | 運行狀態 |
調用次數 | 一個線程只能調用一次 | 可以重復調用 |
運行線程 | 創建了一個子線程,線程名是自己命名的 | 在主線程中調用了一個普通函數 |
注意點 | 想用多線程,必須調用 start() |
Python 中,單線程+異步 I/O 的編程模型
極高的執行效率
子程序切換不是線程切換,而是由程序本身控制,沒有線程切換的開銷
不需要多線程的所機制,只有一個線程,所以不存在同時寫變量沖突,在協程中控制共享資源不用加鎖,只需要判斷狀態就好了,所以執行效率比多線程高很多
要充分利用 CPU 的多核特性,應該使用多進程+協程的方式
感謝各位的閱讀,以上就是“Python的多線程多進程是什么”的內容了,經過本文的學習后,相信大家對Python的多線程多進程是什么這一問題有了更深刻的體會,具體使用情況還需要大家實踐驗證。這里是億速云,小編將為大家推送更多相關知識點的文章,歡迎關注!
免責聲明:本站發布的內容(圖片、視頻和文字)以原創、轉載和分享為主,文章觀點不代表本網站立場,如果涉及侵權請聯系站長郵箱:is@yisu.com進行舉報,并提供相關證據,一經查實,將立刻刪除涉嫌侵權內容。