python的進程和線程經常用到,之前一直不明白threading的join和setDaemon的區別和用法,今天特地研究了一下。multiprocessing中也有這兩個方法,同樣適用,這裡以threading的join和setDaemon舉例。 1、join ()方法:主線程A中,創建了子線程B ...
python的進程和線程經常用到,之前一直不明白threading的join和setDaemon的區別和用法,今天特地研究了一下。multiprocessing中也有這兩個方法,同樣適用,這裡以threading的join和setDaemon舉例。
1、join ()方法:主線程A中,創建了子線程B,並且在主線程A中調用了B.join(),那麼,主線程A會在調用的地方等待,直到子線程B完成操作後,才可以接著往下執行,那麼在調用這個線程時可以使用被調用線程的join方法。
原型:join([timeout])
裡面的參數時可選的,代表線程運行的最大時間,即如果超過這個時間,不管這個此線程有沒有執行完畢都會被回收,然後主線程或函數都會接著執行的。
例子:
# -*- coding: utf-8 -*- from threading import Thread from time import sleep def search(): sleep(5) print 2 if __name__ == '__main__': t = Thread(target=search) t.start() # t.join() print 1
執行後的結果:
1 2
運行後,當列印完1停頓了5秒後才列印2。解釋:線程t開始後,需要睡5s,主線程並沒有等待線程t執行完,就開始往下執行。
現在,我們把t.join()註釋去掉(其他代碼不變),看看有什麼變化,例子:
# -*- coding: utf-8 -*- from threading import Thread from time import sleep def search(): sleep(5) print 2 if __name__ == '__main__': t = Thread(target=search) t.start() t.join() print 1
執行後的結果:
2 1
運行後,發現停頓了5秒後才列印2,然後立即列印了1。解釋:當程式運行到t.join()時,停在了t.join()處,等待線程t執行完,然後開始往下執行。
2.
2、setDaemon()方法。主線程A中,創建了子線程B,並且在主線程A中調用了B.setDaemon(),這個的意思是,把主線程A設置為守護線程,這時候,要是主線程A執行結束了,就不管子線程B是否完成,一併和主線程A退出,這就是setDaemon方法的含義。此外,還有個要特別註意的:必須在start() 方法調用之前設置,如果不設置為守護線程,程式會被無限掛起。
例子:
from threading import Thread from time import sleep def search(): for i in range(5): sleep(1) print 2 if __name__ == '__main__': t = Thread(target=search) # t.setDaemon(True) t.start() print 1
執行後的結果:
1 2 2 2 2
2
運行過程中,程式還沒運行完時,關閉程式。會發現程式還在列印2。這是因為主線程預設等待線程t執行完才關閉,主線程執行完,子線程t沒有執行完,程式就被掛起,一直等待子線程執行完畢。
現在,我們把t.setDaemon(True)的註釋刪掉,再執行查看結果。例子:
# -*- coding: utf-8 -*- from threading import Thread from time import sleep def search(): for i in range(5): sleep(1) print 2 if __name__ == '__main__': t = Thread(target=search) t.setDaemon(True) t.start() print 1
執行結果:
1
執行發現,程式在列印完1後就停止了。這是因為主線程執行完以後,不再等待子線程是否執行完,立馬結束。
threading的join和setDaemon的區別總結:如果主線程中調用了join(),程式會阻塞在調用處,直到子線程執行完才往下執行。如果沒調用,主線程則無需等待,直接往下執行。如果主線程中調用了setDaemon(True),則當程式關閉或者執行完後,子線程立馬關閉,不管其是否執行完。如果主線程中沒有調用setDaemon(True),則當程式關閉或者執行完後,子線程會繼續執行,直到執行完。join管阻塞,setDaemon管結束。
正常開發中,當開啟了多線程,為了不讓程式阻塞,同時主線程關閉時,子線程能夠都同時關閉,會用下麵的方法。
# -*- coding: utf-8 -*- from threading import Thread from time import sleep def search(): for i in range(5): sleep(1) print 2 def insert(): for i in range(5): sleep(0.9) print 3 if __name__ == '__main__': task1 = Thread(target=search) task2 = Thread(target=insert) task1.setDaemon(True) task2.setDaemon(True) task1.start() task2.start() while True: sleep(10)