新聞中心
這篇文章主要講解了“Python的多線程多進(jìn)程是什么”,文中的講解內(nèi)容簡單清晰,易于學(xué)習(xí)與理解,下面請大家跟著小編的思路慢慢深入,一起來研究和學(xué)習(xí)“Python的多線程多進(jìn)程是什么”吧!
成都創(chuàng)新互聯(lián)公司是一家專業(yè)提供施秉企業(yè)網(wǎng)站建設(shè),專注與成都網(wǎng)站制作、成都網(wǎng)站建設(shè)、H5高端網(wǎng)站建設(shè)、小程序制作等業(yè)務(wù)。10年已為施秉眾多企業(yè)、政府機(jī)構(gòu)等服務(wù)。創(chuàng)新互聯(lián)專業(yè)網(wǎng)站制作公司優(yōu)惠進(jìn)行中。
前提
我是參考 Github Python 100 天的文章寫的,再結(jié)合自己的小練習(xí),總結(jié)
最近在面大廠,發(fā)現(xiàn)許多大廠都會(huì)問 Python 的多線程、多進(jìn)程,所以我覺得很有必要總結(jié)學(xué)習(xí)下
什么是進(jìn)程
操作系統(tǒng)中執(zhí)行的一個(gè)程序,類似微信、QQ,每個(gè)程序都是一個(gè)進(jìn)程
概念
它是 CPU 最小資源分配單元
操作系統(tǒng)會(huì)給進(jìn)程分配內(nèi)存空間,每個(gè)進(jìn)程都會(huì)有自己的地址空間、數(shù)據(jù)棧以及其他用于跟蹤進(jìn)程執(zhí)行的輔助數(shù)據(jù)
操作系統(tǒng)管理所有進(jìn)程的執(zhí)行,為它們合理的分配資源
fork、spawn
進(jìn)程可以通過 fork、spawn 的方式來創(chuàng)建新的進(jìn)程來執(zhí)行其他任務(wù)
不過新的進(jìn)程有自己獨(dú)立的內(nèi)存空間、數(shù)據(jù)棧
因此不同進(jìn)程間需要通過通信機(jī)制(IPC)來實(shí)現(xiàn)數(shù)據(jù)共享
常見通信機(jī)制
管道
信號(hào)
套接字
共享內(nèi)存區(qū)
什么是線程
進(jìn)程中可以擁有多個(gè)并發(fā)的執(zhí)行線索
它是 CPU 最小調(diào)度的執(zhí)行單元
特點(diǎn)
同一個(gè)進(jìn)程下的線程共享相同的上下文
相對于進(jìn)程來說,線程間的信息共享和通信更加容易
單核 CPU 系統(tǒng)注意事項(xiàng)
真正的并發(fā)是不可能的
因?yàn)樵谀硞€(gè)時(shí)刻,CPU 只能運(yùn)行唯一的一個(gè)線程
多個(gè)線程共享了 CPU 的執(zhí)行時(shí)間
多線程的好處
提升程序的性能和改善用戶體驗(yàn)
今天日常使用的軟件幾乎都用到了多線程
多線程的壞處
站在其他進(jìn)程的角度,多線程的程序?qū)ζ渌绦虿⒉挥押茫驗(yàn)樗加昧烁嗟?CPU 執(zhí)行時(shí)間,導(dǎo)致其他程序無法獲得足夠的 CPU 執(zhí)行時(shí)間
編寫和調(diào)試多線程的程序?qū)﹂_發(fā)者要求較高
Python 實(shí)現(xiàn)并發(fā)編程的方式
多進(jìn)程
多線程
多進(jìn)程+多線程
Python 中的多進(jìn)程
Linux 下的 fork 函數(shù)
Linux 操作系統(tǒng)上提供了 fork() 系統(tǒng)調(diào)用來創(chuàng)建進(jìn)程
調(diào)用 fork() 函數(shù)的是父進(jìn)程
創(chuàng)建的是子進(jìn)程
子進(jìn)程是父進(jìn)程的拷貝
但子進(jìn)程有自己的 PID
fork() 函數(shù)非常特殊,它會(huì)返回兩次,父進(jìn)程中調(diào)用 fork() 會(huì)返回子進(jìn)程的 PID,子進(jìn)程中調(diào)用 fork() 得到的都是0
Python 提供的 fork 函數(shù)
os 模塊提供了 fork()
Window 下沒有fork()的調(diào)用
實(shí)現(xiàn)跨平臺(tái)的多進(jìn)程變成,可以使用 multiprocessing 模塊的 Process 類來創(chuàng)建子進(jìn)程
還提供了更高級(jí)的封裝,例如批量啟動(dòng)進(jìn)程的進(jìn)程池 pool、用于進(jìn)程間同喜你的隊(duì)列 Queue 和管道 Pipe
使用多進(jìn)程和不使用多進(jìn)程的區(qū)別(寫代碼)
不使用多進(jìn)程
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下載完成! 耗費(fèi)了%d秒' % (filename, time_to_download))def main(): start = time() download_task('Python從入門到住院.pdf') download_task('Peking Hot.avi') end = time()print('總共耗費(fèi)了%.2f秒.' % (end - start))if __name__ == '__main__': main()
執(zhí)行結(jié)果
開始下載Python從入門到住院.pdf... Python從入門到住院.pdf下載完成! 耗費(fèi)了10秒 開始下載Peking Hot.avi... Peking Hot.avi下載完成! 耗費(fèi)了9秒 總共耗費(fèi)了19.02秒.
可以看到需要先等第一個(gè)文件下載完才能下載第二個(gè)文件,效率很低
使用多進(jìn)程
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下載完成! 耗費(fèi)了%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('總共耗費(fèi)了%.2f秒.' % (end - start))if __name__ == '__main__': main2()
執(zhí)行結(jié)果
開始下載Python從入門到住院.pdf... 開始下載Peking Hot.avi... Python從入門到住院.pdf下載完成! 耗費(fèi)了6秒 Peking Hot.avi下載完成! 耗費(fèi)了10秒 總共耗費(fèi)了10.17秒.
兩個(gè)任務(wù)同時(shí)執(zhí)行,總耗時(shí)不再是兩個(gè)任務(wù)的時(shí)間總和
知識(shí)點(diǎn)
Process:通過 Process 類創(chuàng)建進(jìn)程對象
target:通過 target 參數(shù)傳入一個(gè)函數(shù)名來表示進(jìn)程啟動(dòng)后要執(zhí)行的代碼
args:是一個(gè)元組,代表傳遞給函數(shù)的參數(shù)列表
start:Process 的 start() 方法來啟動(dòng)進(jìn)程
join:Process 的 join() 方法表示等待進(jìn)程執(zhí)行結(jié)束,才會(huì)往下執(zhí)行
Python 中的多線程
前言
推薦 threading 模塊來實(shí)現(xiàn)多線程編程,它提供了更好的面向?qū)ο蠓庋b
多線程的實(shí)現(xiàn)方式
#!/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下載完成! 耗費(fèi)了%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('總共耗費(fèi)了%.2f秒.' % (end - start))if __name__ == '__main__': main3()
執(zhí)行結(jié)果
開始下載Python從入門到住院.pdf... 開始下載Peking Hot.avi... Peking Hot.avi下載完成! 耗費(fèi)了6秒 Python從入門到住院.pdf下載完成! 耗費(fèi)了8秒 總共耗費(fèi)了8.01秒.
一樣執(zhí)行效率高很多
自定義線程類
#!/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下載完成! 耗費(fèi)了%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('總共耗費(fèi)了%.2f秒.' % (end - start))if __name__ == '__main__': main3()
執(zhí)行結(jié)果
開始下載Python從入門到住院.pdf... 開始下載Peking Hot.avi... Peking Hot.avi下載完成! 耗費(fèi)了6秒 Python從入門到住院.pdf下載完成! 耗費(fèi)了9秒 總共耗費(fèi)了9.00秒.
也是一樣的高效運(yùn)行
重點(diǎn)知識(shí):start 和 run 方法的區(qū)別
比較點(diǎn) | start | run |
作用 | 啟動(dòng)線程,獲取 CPU 時(shí)間片 | 運(yùn)行線程指定的代碼塊 |
線程狀態(tài) | 可運(yùn)行狀態(tài) | 運(yùn)行狀態(tài) |
調(diào)用次數(shù) | 一個(gè)線程只能調(diào)用一次 | 可以重復(fù)調(diào)用 |
運(yùn)行線程 | 創(chuàng)建了一個(gè)子線程,線程名是自己命名的 | 在主線程中調(diào)用了一個(gè)普通函數(shù) |
注意點(diǎn) | 想用多線程,必須調(diào)用 start() |
Python 中的協(xié)程
什么是協(xié)程
Python 中,單線程+異步 I/O 的編程模型
協(xié)程的優(yōu)勢
極高的執(zhí)行效率
子程序切換不是線程切換,而是由程序本身控制,沒有線程切換的開銷
不需要多線程的所機(jī)制,只有一個(gè)線程,所以不存在同時(shí)寫變量沖突,在協(xié)程中控制共享資源不用加鎖,只需要判斷狀態(tài)就好了,所以執(zhí)行效率比多線程高很多
重點(diǎn)
要充分利用 CPU 的多核特性,應(yīng)該使用多進(jìn)程+協(xié)程的方式
感謝各位的閱讀,以上就是“Python的多線程多進(jìn)程是什么”的內(nèi)容了,經(jīng)過本文的學(xué)習(xí)后,相信大家對Python的多線程多進(jìn)程是什么這一問題有了更深刻的體會(huì),具體使用情況還需要大家實(shí)踐驗(yàn)證。這里是創(chuàng)新互聯(lián),小編將為大家推送更多相關(guān)知識(shí)點(diǎn)的文章,歡迎關(guān)注!
新聞名稱:Python的多線程多進(jìn)程是什么
分享URL:http://ef60e0e.cn/article/ghhihi.html