本文來自於千鋒教育在阿里雲開發者社區學習中心上線課程《Python入門2020最新大課》,主講人姜偉。
多線程實現多任務
在現實生活中,有很多的場景中的事情是同時進行的,比如跳舞和唱歌是同時進行的。
在程序中,可以使用代碼來模擬唱歌和跳舞的功能:
from time import sleep
def sing():
for i in range(3):
print("正在唱歌...%d"%i)
sleep(1)
def dance():
for i in range(3):
print("正在跳舞...%d"%i)
sleep(1)
if __name__ == '__main__':
sing() #唱歌
dance() #跳舞
- 很顯然剛剛的程序並沒有完成唱歌和跳舞同時進行的要求
- 如果想要實現“唱歌跳舞”同時進行,那麼就需要一個新的方法,叫做:多任務
多任務概念
什麼叫“多任務”呢?簡單地說,就是操作系統可以同時運行多個任務。打個比方,你一邊在用瀏覽器上網,一邊在聽MP3,一邊在用Word趕作業,這就是多任務,至少同時有3個任務正在運行。還有很多任務悄悄地在後臺同時運行著,只是桌面上沒有顯示而已。
現在,多核CPU已經非常普及了,但是,即使過去的單核CPU,也可以執行多任務。由於CPU執行代碼都是順序執行的,那麼,單核CPU是怎麼執行多任務的呢?
答案就是操作系統輪流讓各個任務交替執行,任務1執行0.01秒,切換到任務2,任務2執行0.01秒,再切換到任務3,執行0.01秒……這樣反覆執行下去。表面上看,每個任務都是交替執行的,但是,由於CPU的執行速度實在是太快了,我們感覺就像所有任務都在同時執行一樣。
真正的並行執行多任務只能在多核CPU上實現,但是,由於任務數量遠遠多於CPU的核心數量,所以,操作系統也會自動把很多任務輪流調度到每個核心上執行。
對於操作系統來說,一個任務就是一個進程(Process),比如打開一個瀏覽器就是啟動一個瀏覽器進程,打開一個記事本就啟動了一個記事本進程,打開兩個記事本就啟動了兩個記事本進程,打開一個Word就啟動了一個Word進程。
有些進程還不止同時幹一件事,比如Word,它可以同時進行打字、拼寫檢查、打印等事情。在一個進程內部,要同時幹多件事,就需要同時運行多個“子任務”,我們把進程內的這些“子任務”稱為線程(Thread)。
由於每個進程至少要幹一件事,所以,一個進程至少有一個線程。當然,像Word這種複雜的進程可以有多個線程,多個線程可以同時執行,多線程的執行方式和多進程是一樣的,也是由操作系統在多個線程之間快速切換,讓每個線程都短暫地交替運行,看起來就像同時執行一樣。當然,真正地同時執行多線程需要多核CPU才可能實現。
我們前面編寫的所有的Python程序,都是執行單任務的進程,也就是隻有一個線程。如果我們要同時執行多個任務怎麼辦?
有兩種解決方案:
- 一種是啟動多個進程,每個進程雖然只有一個線程,但多個進程可以一塊執行多個任務。
- 還有一種方法是啟動一個進程,在一個進程內啟動多個線程,這樣,多個線程也可以一塊執行多個任務。
當然還有第三種方法,就是啟動多個進程,每個進程再啟動多個線程,這樣同時執行的任務就更多了,當然這種模型更復雜,實際很少採用。
總結一下就是,多任務的實現有3種方式:
- 多進程模式;
- 多線程模式;
- 多進程+多線程模式。
import threading, time
def dance():
for i in range(50):
time.sleep(0.2)
print('我正在跳舞')
def sing():
for i in range(50):
time.sleep(0.2)
print('我正在唱歌')
# 多個任務同時執行
# Python裡執行多任務: 多線程、多進程、多進程+多線程
# dance()
# singe()
# target 需要的是一個函數,用來指定線程需要執行的任務
t1 = threading.Thread(target=dance) # 創建了線程1
t2 = threading.Thread(target=sing) # 創建了線程2
# 啟動線程
t1.start()
t2.start()
注意:
- 併發:指的是任務數多餘cpu核數,通過操作系統的各種任務調度算法,實現用多個任務“一起”執行(實際上總有一些任務不在執行,因為切換任務的速度相當快,看上去一起執行而已)
- 並行:指的是任務數小於等於cpu核數,即任務真的是一起執行的。