【threading】Python 多執行緒threading教學:三大方法一次學會 加速程式的運作速度吧!手把手教到好
一、前言
為何要學threading,當然主要的原因還是想使寫出來的程式跑的更快,把CPU的效能提升,簡單來說你的主程式中可能有很多個子程式,而有的子程式明明互不干預卻要在執行時傻傻排隊,等待處理。使用threading就可以避免這個困擾,可以將不同子程式放在不同執行序(thread)中,在其他序空檔時先上來處理。第二段為多執行序介紹(Multithreading),想要快速上手可以直接看第三段(附完整程式碼)。
還不知道怎麼學python或基礎不穩的可以看:Python學習地圖總覽:課程分類 專案分類 問題解決
部落格教學網站:
https://pixnashpython.pixnet.net/blog
想要即時訂閱最新文章:
https://forms.gle/MdXmiF2HgHhNChL46
訂閱Telegram來接收最新資訊:
https://t.me/joinchat/VUUuDt67Uq5l6CIQ
二、什麼是多執行序(Multithreading)
可以將同一應用中的操作分為不同的執行緒。各執行緒可以平行執行。
作業系統除了會將處理時間分配給不同的應用,也會分給同一個應用不同執行緒。
簡單說,將一個應用分為多個執行緒,分別可能有介面執行緒、資料擷取及 記錄執行緒等。
可以排定各個執行緒的優先順序,在單一執行續空檔時間或等待期間先切換到不同執行續去完成其他工作,
達到提升CPU效能的目的。而不是在原地傻傻的排隊,如果運用得當可能會有同步運作的錯覺~
三、threading手把手教到好
(1) 基本用法
threading的基本用法很簡單,先import threading後,遵循幾大步驟:
1. 先定義出你要執行的方法(函數、子程式等)
2. 將你要運行的程式使用threading.Thread()加入其中,參數:target=你的方法(子程式)、args=(你的方法所需的參數)
3. Thread.start() 開始運行
4. Thread.join() 等待結束
5. 如果要在執行一次從第2開始先加入(意思是放入的程序方法在使用start、join後就沒了)
完整程式碼
import threading
## 基本用法 --------------------------------------------------- #
def job(name): # 要被執行的方法(函數)
print("HI " + name)
# 放入執行序中
t = threading.Thread(target=job, args=('Nash',)) #
t.start() # 開始
t.join() # 等待結束
(2) 一池子thread用法
大部份的都是遇到一次要執行一堆子程式的問題,這時候先創立一個list,方便存放要排隊或執行的執行序,而後使用迴圈分別start及join即可。
完整程式碼
import threading
## 一池子thread用法 --------------------------------------------------- #
# 子執行緒的工作函數
def job(name):
print("HI " + name)
# 建立存放執行序的list(存放thread)
threads = []
# 放入執行序
t = threading.Thread(target=job, args=('Nash',)) #
threads.append(t) # 將程序放入threads
# 開始
for t in threads:
t.start()
# 等待所有子執行緒結束
for t in threads:
t.join()
(3) 在class內的用法
同時也常遇到需要再class內呼叫一堆子程序的問題,其中有兩個解決方法,至於哪個會處理的比較快可能要視開發者的程式而定,這兩個常見方法分別:
1. 另外寫一個類(class)專門給(執行序)thread而使用,要用在呼叫。
2. 直接快速的寫在主類中,定義thread函數,也就是我下面要說的方法。
下面我想在runner自訂一個執行序專門給 job(name)使用,而且我想不斷的呼叫job。
首先我先定義 thread_job(self)把我想執行的子程式放入,一樣使用 threading.Thread,
而後我在 __init__(self):時先呼叫一次 thread_job把工作放入self.threads = [],
最後定義 thread_start(self)負責來執行全部的序(thread)及等待結束。
同時再呼叫一次 self.thread_job(),把工作再次放入self.threads = []中,完成循環。
還不懂類class的可以看 :【Python基礎】什麼是class類:五分鐘看完文章馬上懂物件導向及寫code
完整程式碼
import threading ## 在class內的用法 --------------------------------------------------- # class runner(object): def __init__(self): self.thread_job() # 定義程序清單 def job(name): # 程序1 print("HI " + name) def thread_job(self): # 定義線程清單 self.threads = [] t = threading.Thread(target=job, args=('Nash',)) self.threads.append(t) def thread_start(self): # 開始線程 for t in self.threads: t.start() # 開始 for t in self.threads: t.join() # 等待結束 self.thread_job() run = runner() # 生成物件 run.thread_start() 使用方法
四、後記
除了多執行序處理python還有使程式多核處理的方法,下次讓我帶大家來看看吧,threading很簡單使用而且在python不用另外pip install,幾個步驟就可以加快程式運作。
還不知道怎麼學python或基礎不穩的可以看:Python學習地圖總覽:課程分類 專案分類 問題解決
部落格教學網站:
https://pixnashpython.pixnet.net/blog
想要即時訂閱最新文章:
https://forms.gle/MdXmiF2HgHhNChL46
訂閱Telegram來接收最新資訊:
https://t.me/joinchat/VUUuDt67Uq5l6CIQ

您好,無意中看到文中描述與程式碼有一些疏漏, 在此提出與您共勉: 1. Multi threading不會讓CPU的效能提高,CPU的效能是固定的,multi thread只能讓你寫出來的軟體善用CPU的效能,提升的是軟體執行效能,而非CPU的效能 2. 不同子程式放在不同執行緒中,子程式並非在其他執行緒的空擋執行,每個執行緒(無論是你的主程式、子程式或是同時間在執行的其他程式)都是透過作業系統的排程依照排成演算法輪流被CPU服務。但是我們從每個執行緒的角度來看,自己的時間永遠都是連續的,在抽象化上執行緒感受不到也不應感受到自己有被暫停過,這點就如同你說的他們是被平行處理的,所以不存在所謂空擋,空檔是作業系統安排的CPU time slice,無論你的執行緒現在是否在進行運算,作業系統依然會不定期中斷你去服務別人 3. 在工程上我們應先對問題作抽象化,並將同質性高的問題歸一處理。標題中點出threading的三大用法,但文中提出的三大用法不外乎: 產生thread物件->assign一個non-blocking任務->join等待任務完成 其實根本上是同一種用法在三種不同場景的應用,變化的是場景而非用法 在軟體中平行處理有諸如synchronize、asynchronize等不同實現,在應對共有資料時還有racing condition的問題,處理racing condition又有多種不同方式 所以所謂不同用法,包括但不限於我這邊的舉例:a. 無參數多任務、b. 有參數多任務但參數間獨立無相關、c. 多任務且任務間會操作到同樣變數 b與a相比參數賦予的順序可能會影響任務的執行,而c與前兩者相比因為有racing condition所以會有鎖定與互鎖的應用 4. 所有的範例都用print這個non-block的函數做為任務標的,無法體現出多執行緒「平行處理」的感覺,最後一個class的範例甚至建立了一個永遠只會有一個thread的list,這麼做建立這個list還有何意義呢? 每個人對於同一個概念的理解多少會有出入。但既非學習筆記;而是以教學之名分享自己的知識與理解,還號稱手把手教到好,那就應該負起當別人老師的責任對自己的教學內容再三斟酌 若有考慮不周之處再請賜教 謝謝,Slow
贊同#1的留言。 身為也同樣在部落格分享些自學程式的內容的人,深感如何平衡文章深度並同時保持嚴謹的內容是一個難處,或許版主是希望以啟顯易懂的方式降低初學者入門多執行序的壓力,但多執行序是個相當難的問題,保有嚴謹的深刻的了解對長遠的學習才有益處。