如何改變 Python 中線程的執行順序

2021-10-24 13:29:57 字數 4833 閱讀 9849

一、主線程會等待所有的子執行緒結束後才結束

首先我看下最普通情況下,主線程和子執行緒的情況。

import threading

from time import sleep, ctime

defsing()

:for i in

range(3

):print

("正在唱歌...%d"

% i)

sleep(1)

defdance()

:for i in

range(3

):print

("正在跳舞...%d"

% i)

sleep(1)

if __name__ ==

'__main__'

:print

('---開始---:%s'

% ctime())

t1 = threading.thread(target=sing)

t2 = threading.thread(target=dance)

t1.start(

) t2.start(

)print

('---結束---:%s'

% ctime(

))

執行結果:

最後一行列印的**就算在一開始執行了,程式也不會結束。

只有等待所有的子執行緒(sing 和 dance)都執行完畢,主線程才會結束,即程式結束。

二、預設狀態下,多執行緒的執行順序是不確定的

我們先來看一段**:

'''

'''import threading

import time

class

mythread

(threading.thread)

:def

run(self)

:for i in

range(3

):time.sleep(1)

msg =

"i'm "

+self.name+

' @ '

+str

(i)print

(msg)

deftest()

:for i in

range(5

):t = mythread(

) t.start(

)if __name__ ==

'__main__'

: test(

)

執行結果:

i'm thread-

1 @ 0

i'm thread-

2 @ 0

i'm thread-

3 @ 0

i'm thread-

4 @ 0

i'm thread-

5 @ 0

i'm thread-

1 @ 1

i'm thread-

3 @ 1

i'm thread-

2 @ 1

i'm thread-

4 @ 1

i'm thread-

5 @ 1

i'm thread-

1 @ 2

i'm thread-

3 @ 2

i'm thread-

2 @ 2

i'm thread-

4 @ 2

i'm thread-

5 @ 2

每次的執行結果可能都不一樣,但大體差不多。

說明:從**和執行結果我們可以看出,多執行緒程式的執行順序是不確定的。

當執行到 sleep 語句時,執行緒將被阻塞,到 sleep 結束後,執行緒進入就緒狀態,等待排程,而執行緒排程將自行選擇乙個執行緒執行。

上面的**中只能保證每個執行緒都執行完整個 run 函式,但是執行緒的啟動順序、run 函式中每次迴圈的執行順序都不能確定。

總結每個執行緒預設有乙個名字,儘管上面的例子中沒有指定執行緒物件的 name,但是 python 會自動為執行緒指定乙個名字。

當執行緒的 run() 方法結束時該執行緒完成。

無法控制線程排程程式,但可以通過別的方式來影響執行緒排程的方式。

三、python daemon 守護執行緒詳解

當程式中擁有多個執行緒時,主線程執行結束並不會影響子執行緒繼續執行。

換句話說,只有程式中所有執行緒全部執行完畢後,程式才算真正結束。

python 還支援建立另一種執行緒,稱為守護執行緒(或後台執行緒)。

此類執行緒的特點是,當程式中主線程及所有非守護執行緒執行結束時,未執行完畢的守護執行緒也會隨之消亡,程式將結束執行。

守護執行緒本質也是執行緒,因此其建立方式和普通執行緒一樣,唯一不同之處在於,將普通執行緒設為守護執行緒,需通過執行緒物件呼叫其 damon 屬性,將該屬性的值改為 true。

注意:執行緒物件呼叫 daemon 屬性必須在呼叫 start() 方法之前,否則 python 直譯器將報 runtimeerror 錯誤。

'''

'''import threading

defaction

(len):

for i in

range

(len):

print

(threading.current_thread(

).getname()+

","+

str(i)

)def

main()

: t1 = threading.thread(target=action, args=(10

,))# 設定子執行緒為守護程序

t1.daemon =

true

t1.start(

)for i in

range(3

):print

(threading.current_thread(

).getname()+

','+

str(i)

)if __name__ ==

"__main__"

: main(

)

執行結果:

thread-1,

0mainthread,

0mainthread,

1mainthread,

2

程式中,子執行緒裡的程式就迴圈了一次,接著主線程執行完後,子執行緒就不列印資訊了。

由於該程式中除了守護執行緒就只有主線程,因此只要主線程執行結束,則守護執行緒也隨之消亡。

四、控制線程執行順序

通過前面的學習我們知道,主線程和子執行緒會輪流獲得 cpu 的資源。

但有時候,我們想讓某個子執行緒先執行,然後再讓主線程執行**,該如何實現呢?

很簡單,通過呼叫執行緒物件的 join() 方法即可。

join() 方法的功能是在程式指定位置,優先讓該方法的呼叫者使用 cpu 資源。

該方法的語法格式如下:

thread.join(

[timeout]

)

timeout 引數作為可選引數,其功能是指定 thread 執行緒最多可以霸佔 cpu 資源的時間(以秒為單位)。

如果省略,則缺省直到 thread 執行結束(進入死亡狀態)才釋放 cpu 資源。

我們仍舊拿上面的例子來舉例:

'''

'''import threading

defaction

(len):

for i in

range

(len):

print

(threading.current_thread(

).getname()+

","+

str(i)

)def

main()

: t1 = threading.thread(target=action, args=(10

,))# 設定子執行緒為守護程序

t1.daemon =

true

t1.start(

) t1.join(

)for i in

range(3

):print

(threading.current_thread(

).getname()+

','+

str(i)

)if __name__ ==

"__main__"

: main(

)

我們在子執行緒呼叫的後面,新增了 t1.join()。

執行結果:

thread-1,

0thread-1,

1thread-1,

2thread-1,

3thread-1,

4thread-1,

5thread-1,

6thread-1,

7thread-1,

8thread-1,

9mainthread,

0mainthread,

1mainthread,

2

上面的例子中,t1 執行緒呼叫了 join() 方法,並且沒有指定具體的 timeout 引數值。

這意味著如果程式想繼續往下執行,必須先執行完 t1 子執行緒。

如何改變 Python 中線程的執行順序

首先我看下最普通情況下,主線程和子執行緒的情況。import threading from time import sleep,ctime def sing for i in range 3 print 正在唱歌.d i sleep 1 def dance for i in range 3 prin...

改變 Python 中線程執行順序的方法

一 主線程會等待所有的子執行緒結束後才結束 首先我看下最普通情況下,主線程和子執行緒的情況。import threading from time import sleep,ctime def sing for i in range 3 print 正在唱歌.d i sleep 1 def dance...

python中線程

程序和執行緒的區別 1.程序 每個程式都會有乙個程序,負責管理程式各個功能的執行,程序只會有乙個 而且至少有乙個 相當於包工頭 2.執行緒 每個程序裡面至少有乙個執行緒,稱之為主線程,除此以外還會有其他執行緒,稱之為分執行緒 執行緒是控制任務執行的最小單位 相當於農名工 3.程序負責控制各個執行緒的...