在 Python 的多線程編程中,常常碰到 thread.join()這樣的代碼。那麼今天我們用實際代碼來解釋一下 join 函數的做用。python
第一,當一個進程啓動以後,會默認產生一個主線程,由於線程是程序執行流的最小單元,當設置多線程時,主線程會建立多個子線程,在python中,默認狀況下(其實就是setDaemon(False)),主線程執行完本身的任務之後,就退出了,此時子線程會繼續執行本身的任務,直到本身的任務結束,例子見下面。編程
# coding: utf-8 # 測試多線程中join的功能 import threading, time def doWaiting(): print 'start waiting1: ' + time.strftime('%H:%M:%S') + "\n" time.sleep(3) print 'stop waiting1: ' + time.strftime('%H:%M:%S') + "\n" def doWaiting1(): print 'start waiting2: ' + time.strftime('%H:%M:%S') + "\n" time.sleep(8) print 'stop waiting2: ', time.strftime('%H:%M:%S') + "\n" tsk = [] thread1 = threading.Thread(target = doWaiting) thread1.start() tsk.append(thread1) thread2 = threading.Thread(target = doWaiting1) thread2.start() tsk.append(thread2) print 'start join: ' + time.strftime('%H:%M:%S') + "\n" print 'end join: ' + time.strftime('%H:%M:%S') + "\n"
代碼執行結果以下:多線程
start waiting1: 22:24:20 start join: 22:24:20 start waiting2: 22:24:20 end join: 22:24:20 stop waiting1: 22:24:23 stop waiting2: 22:24:28
第二,當咱們使用setDaemon(True)方法,設置子線程爲守護線程時,主線程一旦執行結束,則所有線程所有被終止執行,可能出現的狀況就是,子線程的任務尚未徹底執行結束,就被迫中止,例子見下面。app
1 # coding: utf-8 2 # 測試多線程中join的功能 3 import threading, time 4 def doWaiting(): 5 print 'start waiting1: ' + time.strftime('%H:%M:%S') + "\n" 6 time.sleep(3) 7 print 'stop waiting1: ' + time.strftime('%H:%M:%S') + "\n" 8 def doWaiting1(): 9 print 'start waiting2: ' + time.strftime('%H:%M:%S') + "\n" 10 time.sleep(8) 11 print 'stop waiting2: ', time.strftime('%H:%M:%S') + "\n" 12 tsk = [] 13 thread1 = threading.Thread(target = doWaiting) 14 thread1.setDaemon(True) 15 thread1.start() 16 tsk.append(thread1) 17 thread2 = threading.Thread(target = doWaiting1) 18 thread2.setDaemon(True) 19 thread2.start() 20 tsk.append(thread2) 21 print 'start join: ' + time.strftime('%H:%M:%S') + "\n" 22 23 print 'end join: ' + time.strftime('%H:%M:%S') + "\n"
代碼執行結果以下:函數
start waiting1: 22:34:46 start waiting2: 22:34:46 start join: 22:34:46 end join: 22:34:46
第三,沒有設置守護線程且沒有設置join函數的timeout參數時,主線程將會一直等待,直到子線程所有結束,主線程才結束,程序退出。代碼以下:測試
1 # coding: utf-8 2 # 測試多線程中join的功能 3 import threading, time 4 def doWaiting(): 5 print 'start waiting1: ' + time.strftime('%H:%M:%S') + "\n" 6 time.sleep(3) 7 print 'stop waiting1: ' + time.strftime('%H:%M:%S') + "\n" 8 def doWaiting1(): 9 print 'start waiting2: ' + time.strftime('%H:%M:%S') + "\n" 10 time.sleep(8) 11 print 'stop waiting2: ', time.strftime('%H:%M:%S') + "\n" 12 tsk = [] 13 thread1 = threading.Thread(target = doWaiting) 14 thread1.start() 15 tsk.append(thread1) 16 thread2 = threading.Thread(target = doWaiting1) 17 thread2.start() 18 tsk.append(thread2) 19 print 'start join: ' + time.strftime('%H:%M:%S') + "\n" 20 for tt in tsk: 21 tt.join() 22 print 'end join: ' + time.strftime('%H:%M:%S') + "\n"
代碼執行結果以下:spa
start waiting1: 22:41:50 start join: 22:41:50 start waiting2: 22:41:50 stop waiting1: 22:41:53 stop waiting2: 22:41:58 end join: 22:41:58
第四,當沒有設置守護線程且join函數的參數timeout=2時,主線程將會等待多個子線程timeout的累加和這樣的一段時間,時間一到,主線程結束,可是並無殺死子線程,子線程依然能夠繼續執行,直到子線程所有結束,程序退出。代碼以下:線程
1 # coding: utf-8 2 # 測試多線程中join的功能 3 import threading, time 4 def doWaiting(): 5 print 'start waiting1: ' + time.strftime('%H:%M:%S') + "\n" 6 time.sleep(3) 7 print 'stop waiting1: ' + time.strftime('%H:%M:%S') + "\n" 8 def doWaiting1(): 9 print 'start waiting2: ' + time.strftime('%H:%M:%S') + "\n" 10 time.sleep(8) 11 print 'stop waiting2: ', time.strftime('%H:%M:%S') + "\n" 12 tsk = [] 13 thread1 = threading.Thread(target = doWaiting) 14 thread1.start() 15 tsk.append(thread1) 16 thread2 = threading.Thread(target = doWaiting1) 17 thread2.start() 18 tsk.append(thread2) 19 print 'start join: ' + time.strftime('%H:%M:%S') + "\n" 20 for tt in tsk: 21 tt.join(2) 22 print 'end join: ' + time.strftime('%H:%M:%S') + "\n"
代碼執行結果以下:code
start waiting1: 23:02:34 start waiting2: 23:02:34 start join: 23:02:34 stop waiting1: 23:02:37 end join: 23:02:38 stop waiting2: 23:02:42
第五,當設置守護線程join函數的參數timeout=2時,主線程將會等待多個子線程timeout的累加和這樣的一段時間,時間一到,主線程結束,殺死未執行完的子線程,程序退出。代碼以下:blog
1 # coding: utf-8 2 # 測試多線程中join的功能 3 import threading, time 4 def doWaiting(): 5 print 'start waiting1: ' + time.strftime('%H:%M:%S') + "\n" 6 time.sleep(3) 7 print 'stop waiting1: ' + time.strftime('%H:%M:%S') + "\n" 8 def doWaiting1(): 9 print 'start waiting2: ' + time.strftime('%H:%M:%S') + "\n" 10 time.sleep(8) 11 print 'stop waiting2: ', time.strftime('%H:%M:%S') + "\n" 12 tsk = [] 13 thread1 = threading.Thread(target = doWaiting) 14 thread1.setDaemon(True) 15 thread1.start() 16 tsk.append(thread1) 17 thread2 = threading.Thread(target = doWaiting1) 18 thread2.setDaemon(True) 19 thread2.start() 20 tsk.append(thread2) 21 print 'start join: ' + time.strftime('%H:%M:%S') + "\n" 22 for tt in tsk: 23 tt.join(2) 24 print 'end join: ' + time.strftime('%H:%M:%S') + "\n"
代碼執行結果以下:
start waiting1: 23:23:57 start waiting2: 23:23:57 start join: 23:23:57 stop waiting1: 23:24:00 end join: 23:24:01