執行緒的生命週期

2022-08-13 05:06:22 字數 3483 閱讀 7697

當執行緒被建立並啟動後,並不會直接進入執行狀態,也不會一直處於執行狀態,執行緒的生命週期中,它會經歷新建(new)、就緒(ready)、執行(running)、阻塞(blocked)和死亡(dead)5 種狀態。當執行緒啟動以後,它不可能一直「霸佔」著 cpu 獨自執行。所以 cpu 需要在多個執行緒之間切換,於是執行緒的狀態也會多次在執行、就緒之間轉換。

當程式建立了乙個 thread 物件或 thread 子類的物件之後,該執行緒就處於新建狀態,和其他的 python 物件一樣,此時的執行緒物件並沒有表現出任何執行緒的動態特徵,程式也不會執行執行緒執行體(target)。

當執行緒物件呼叫 start() 方法之後,該執行緒處於就緒狀態,python 直譯器會為其建立方法呼叫棧和程式計數器,處於這種狀態中的執行緒並沒有開始執行,只是表示該執行緒可以執行了。至於該執行緒何時開始執行,取決於 python 直譯器中線程排程器的排程(cpu的排程)。

注意,啟動執行緒使用 start() 方法,而不是 run() 方法。呼叫 start() 方法來啟動執行緒,系統會把該 run() 方法當成執行緒執行體來處理;但如果直接呼叫執行緒物件的 run() 方法,則 run() 方法立即就會被執行,而且在該方法返回之前其他執行緒無法併發執行。也就是說,如果直接呼叫執行緒物件的 run() 方法,則系統會把執行緒物件當成乙個普通物件,而 run() 方法是乙個普通方法,不是執行緒執行體。

import

threading

#定義準備作為執行緒執行體的action函式

defaction(max):

for i in

range(max):

#直接呼叫run()方法時,thread的name屬性返回的是該物件的名字

#而不是當前執行緒的名字

#使用threading.current_thread().name總是獲取當前執行緒的名字

print(threading.current_thread().name + "

" + str(i)) #

①for i in range(100):

#呼叫thread的currentthread()方法獲取當前執行緒

print(threading.current_thread().name + "

" +str(i))

if i == 20:

#直接呼叫執行緒物件的run()方法

#系統會把執行緒物件當成普通物件,把run()方法當成普通方法

#所以下面兩行**並不會啟動兩個執行緒,而是依次執行兩個run()方法

threading.thread(target=action,args=(100,)).run()

threading.thread(target=action,args=(100,)).run()

啟動執行緒的正確方法是呼叫 thread 物件的 start() 方法,而不是直接呼叫 run() 方法,否則就變成單執行緒程式了。

注意,只能對處於新建狀態的執行緒呼叫 start() 方法。也就是說,如果程式對同乙個執行緒重複呼叫 start() 方法,將引發 runtimeerror 異常。

如果處於就緒狀態的執行緒獲得了 cpu,開始執行 run() 方法的執行緒執行體,則該執行緒處於執行狀態。

如果計算機只有乙個 cpu,那麼在任何時刻只有乙個執行緒處於執行狀態。當然,在乙個具有多處理器的機器上,將會有多個執行緒並行(parallel)執行;當執行緒數大於處理器數時,依然會存在多個執行緒在同乙個 cpu 上輪換的情況。

當乙個執行緒開始執行後,它不可能一直處於執行狀態(除非它的執行緒執行體足夠短,瞬間就執行結束了),執行緒在執行過程中需要被中斷,目的是使其他執行緒獲得執行的機會,執行緒排程的細節取決於底層平台所採用的策略。對於採用搶占式排程策略的系統而言,系統會給每乙個可執行的執行緒乙個小時間段來處理任務;當該時間段用完後,系統就會剝奪該執行緒所占用的資源,讓其他執行緒獲得執行的機會。在選擇下乙個執行緒時,系統會考慮執行緒的優先順序。

所有現代的桌面和伺服器作業系統都採用搶占式排程策略,但一些小型裝置如手機等則可能採用協作式排程策略,在這樣的系統中,只有當乙個執行緒呼叫了它的 sleep() 或 yield() 方法後才會放棄其所占用的資源(也就是必須由該執行緒主動放棄其所占用的資源)。

當發生如下情況時,執行緒將會進入阻塞狀態:

當前正在執行的執行緒被阻塞之後,其他執行緒就可以獲得執行的機會。被阻塞的執行緒會在合適的時候重新進入就緒狀態,注意是就緒狀態,而不是執行狀態。也就是說,被阻塞執行緒的阻塞解除後,必須重新等待執行緒排程器再次排程它。

針對上面幾種情況,當發生如下特定的情況時可以解除阻塞,讓該執行緒重新進入就緒狀態:

執行緒從阻塞狀態只能進入就緒狀態,無法直接進入執行狀態。就緒和執行狀態之間的轉換通常不受程式控制,而是由系統執行緒排程所決定的,當處於就緒狀態的執行緒獲得處理器資源時,該執行緒進入執行狀態;當處於執行狀態的執行緒失去處理器資源時,該執行緒進入就緒狀態。

執行緒會以如下方式結束,結束後就處於死亡狀態:

注意,當主線程結束時,其他執行緒不受任何影響,並不會隨之結束。一旦子執行緒啟動起來後,它就擁有和主線程相同的地位,不會受主線程的影響。

為了測試某個執行緒是否己經死亡,可以呼叫執行緒物件的 is_alive() 方法,當執行緒處於就緒、執行、阻塞三種狀態時,該方法將返回 true;當執行緒處於新建、死亡兩種狀態時,該方法將返回 false。

不要試圖對乙個已經死亡的執行緒呼叫 start() 方法使它重新啟動,死亡就是死亡,該執行緒將不可再次作為執行緒執行。

import

threading

#定義action函式準備作為執行緒執行體使用

defaction(max):

for i in range(100):

print(threading.current_thread().name + "

" +str(i))

#建立執行緒物件

sd = threading.thread(target=action, args=(100,))

for i in range(300):

#呼叫threading.current_thread()函式獲取當前執行緒

print(threading.current_thread().name + "

" +str(i))

if i == 20:

#啟動執行緒

sd.start()

#判斷啟動後執行緒的is_alive()值,輸出true

print

(sd.is_alive())

#當執行緒處於新建、死亡兩種狀態時,is_alive()方法返回false

#當i > 20時,該執行緒肯定已經啟動過了,如果sd.is_alive()為false時

#那就是死亡狀態了

if i > 20 and

not(sd.is_alive()):

#試圖再次啟動該執行緒

sd.start()

報錯:runtimeerror: threads can only be started once

執行緒生命週期

今天看到一段這樣的 handle hthread createthread null,0,add,a,0,null hmutext createmutex null,false,l huchiti closehandle hthread 簡單的說,關閉了執行緒控制代碼 關閉了執行緒,其兩者的生命週期...

執行緒生命週期

本章目標 了解執行緒的生命週期 了解執行緒的停止操作 執行緒的生命週期 注意大部分的執行緒生命週期的方法基本上都已經學過了,那麼在這裡有以下三個新方法 suspend 方法 暫時掛起執行緒 resume 方法 恢復掛起的執行緒 stop 方法 停止執行緒 但是對於執行緒中suspend resume...

執行緒生命週期

執行緒的生命週期分為五種狀態 新建狀態 就緒狀態 執行狀態 阻塞狀態 死亡狀態 剛new出來的執行緒物件。新建狀態呼叫start 方法就進入就緒狀態。就緒狀態的執行緒又叫做可執行狀態,表示當前執行緒具有搶奪cpu時間片的權利 cpu時間片就是執行權 當乙個執行緒搶奪到cpu時間片之後就開始執行run...