Python中threading的join和setDaemon的區別及用法
Python多線程編程時經常會用到join()和setDaemon()方法,基本用法如下:
join([time]): 等待至線程中止。這阻塞調用線程直至線程的join() 方法被調用中止-正常退出或者拋出未處理的異常-或者是可選的超時發生。 setDaemon,將該線程標記為守護線程或用戶線程1、join ()方法:主線程A中,創建了子線程B,並且在主線程A中調用了B.join(),那麽,主線程A會在調用的地方等待,直到子線程B完成操作後,才可以接著往下執行,那麽在調用這個線程時可以使用被調用線程的join方法。
原型:join([timeout]),裏面的參數時可選的,代表線程運行的最大時間,即如果超過這個時間,不管這個此線程有沒有執行完畢都會被回收,然後主線程或函數都會接著執行的。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 |
import threading
import time
class MyThread(threading.Thread):
def __init__( self , id ):
threading.Thread.__init__( self )
self . id = id
def run( self ):
x = 0
time.sleep( 10 )
print ( self . id )
print ( ‘線程結束:‘ + str (time.time()))
if __name__ = = "__main__" :
t1 = MyThread( 999 )
print ( ‘線程開始:‘ + str (time.time()))
t1.start()
print ( ‘主線程打印開始:‘ + str (time.time()))
for i in range ( 5 ):
print (i)
time.sleep( 2 )
print ( ‘主線程打印結束:‘ + str (time.time()))
|
線程開始:1497534590.2784667
主線程打印開始:1497534590.2794669
0
1
2
3
4
主線程打印結束:1497534592.279581
999
線程結束:1497534600.2800388
從打印結果可知,線程t1 start後,主線程並沒有等線程t1運行結束後再執行,而是在線程執行的同時,執行了後面的語句。
現在,把join()方法加到啟動線程後面(其他代碼不變)
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 |
import threading
import time
class MyThread(threading.Thread):
def __init__( self , id ):
threading.Thread.__init__( self )
self . id = id
def run( self ):
x = 0
time.sleep( 10 )
print ( self . id )
print ( ‘線程結束:‘ + str (time.time()))
if __name__ = = "__main__" :
t1 = MyThread( 999 )
print ( ‘線程開始:‘ + str (time.time()))
t1.start()
t1.join()
print ( ‘主線程打印開始:‘ + str (time.time()))
for i in range ( 5 ):
print (i)
time.sleep( 2 )
print ( ‘主線程打印結束:‘ + str (time.time()))
|
線程開始:1497535176.5019968
999
線程結束:1497535186.5025687
主線程打印開始:1497535186.5025687
0
1
2
3
4
主線程打印結束:1497535188.5026832
線程t1 start後,主線程停在了join()方法處,等子線程t1結束後,主線程繼續執行join後面的語句。
2、setDaemon()方法。主線程A中,創建了子線程B,並且在主線程A中調用了B.setDaemon(),這個的意思是,把主線程A設置為守護線程,這時候,要是主線程A執行結束了,就不管子線程B是否完成,一並和主線程A退出.這就是setDaemon方法的含義,這基本和join是相反的。此外,還有個要特別註意的:必須在start() 方法調用之前設置。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 |
import threading
import time
class MyThread(threading.Thread):
def __init__( self , id ):
threading.Thread.__init__( self )
self . id = id
def run( self ):
x = 0
time.sleep( 10 )
print ( self . id )
print ( "This is:" + self .getName()) # 獲取線程名稱
print ( ‘線程結束:‘ + str (time.time()))
if __name__ = = "__main__" :
t1 = MyThread( 999 )
print ( ‘線程開始:‘ + str (time.time()))
t1.setDaemon( True )
t1.start()
print ( ‘主線程打印開始:‘ + str (time.time()))
for i in range ( 5 ):
print (i)
time.sleep( 2 )
print ( ‘主線程打印結束:‘ + str (time.time()))
|
線程開始:1497536678.8509264
主線程打印開始:1497536678.8509264
0
1
2
3
4
主線程打印結束:1497536680.8510408
t1.setDaemon(True)的操作,將子線程設置為了守護線程。根據setDaemon()方法的含義,父線程打印內容後便結束了,不管子線程是否執行完畢了。
如果在線程啟動前沒有加t1.setDaemon(True),輸出結果為:
線程開始:1497536865.3215919
主線程打印開始:1497536865.3215919
0
1
2
3
4
主線程打印結束:1497536867.3217063
999
This is:Thread-1
線程結束:1497536875.3221638
程序運行中,執行一個主線程,如果主線程又創建一個子線程,主線程和子線程就分兵兩路,分別運行,那麽當主線程完成想退出時,會檢驗子線程是否完成,如果子線程未完成,則主線程會等待子線程完成後再退出;
有時我們需要的是,子線程運行完,才繼續運行主線程,這時就可以用join方法(在線程啟動後面);
但是有時候我們需要的是,只要主線程完成了,不管子線程是否完成,都要和主線程一起退出,這時就可以用setDaemon方法(在線程啟動前面)。
參考博客:http://www.cnblogs.com/UncleYong/p/6987112.html
Python中threading的join和setDaemon的區別及用法