Python多線程以及多線程中join()的使用方法示例
Python多線程與多進程中join()方法的效果是相同的。
下面僅以多線程為例:
首先需要明確幾個概念:
知識點一:
當一個進程啟動之后,會默認產(chǎn)生一個主線程,因為線程是程序執(zhí)行流的最小單元,當設置多線程時,主線程會創(chuàng)建多個子線程,在python中,默認情況下(其實就是setDaemon(False)),主線程執(zhí)行完自己的任務以后,就退出了,此時子線程會繼續(xù)執(zhí)行自己的任務,直到自己的任務結(jié)束,
見下面 例子一。
知識點二:
當我們使用setDaemon(True)方法,設置子線程為守護線程時,主線程一旦執(zhí)行結(jié)束,則全部線程全部被終止執(zhí)行,可能出現(xiàn)的情況就是,子線程的任務還沒有完全執(zhí)行結(jié)束,就被迫停止,
見下面例子二。
知識點三:
此時join的作用就凸顯出來了,join所完成的工作就是線程同步,即主線程任務在設置join函數(shù)的地方,進入阻塞狀態(tài),一直等待其他的子線程執(zhí)行結(jié)束之后,主線程再開始執(zhí)行直到終止終止,
例子見下面三。
知識點四:
join有一個timeout參數(shù):
- 當有設置守護線程時,含義是主線程對于子線程等待timeout的時間將會殺死該子線程,最后退出程序。所以說,如果有10個子線程,全部的等待時間就是每個timeout的累加和。簡單的來說,就是給每個子線程一個timeout的時間,讓他去執(zhí)行,時間一到,不管任務有沒有完成,直接殺死。
- 沒有設置守護線程時,主線程將會等待timeout的累加和這樣的一段時間,時間一到,主線程結(jié)束,但是并沒有殺死子線程,子線程依然可以繼續(xù)執(zhí)行,直到子線程全部結(jié)束,程序退出。
一:Python多線程的默認情況
import threading
import time
def run():
time.sleep(2)
print('當前線程的名字是: ', threading.current_thread().name)
time.sleep(2)
if __name__ == '__main__':
start_time = time.time()
print('這是主線程:', threading.current_thread().name)
thread_list = []
for i in range(5):
t = threading.Thread(target=run)
thread_list.append(t)
for t in thread_list:
t.start()
print('主線程結(jié)束!' , threading.current_thread().name)
print('一共用時:', time.time()-start_time)
其執(zhí)行結(jié)果如下:

關(guān)鍵:
- 計時是對主線程計時,主線程結(jié)束,計時隨之結(jié)束,打印出主線程的用時。
- 主線程的任務完成之后,主線程隨之結(jié)束,子線程繼續(xù)執(zhí)行自己的任務,直到全部的子線程的任務全部結(jié)束,程序結(jié)束。
二:設置守護線程
import threading
import time
def run():
time.sleep(2)
print('當前線程的名字是: ', threading.current_thread().name)
time.sleep(2)
if __name__ == '__main__':
start_time = time.time()
print('這是主線程:', threading.current_thread().name)
thread_list = []
for i in range(5):
t = threading.Thread(target=run)
thread_list.append(t)
for t in thread_list:
t.setDaemon(True)
t.start()
print('主線程結(jié)束了!' , threading.current_thread().name)
print('一共用時:', time.time()-start_time)
注意:注意請確保setDaemon()在start()之前
其執(zhí)行結(jié)果如下:

關(guān)鍵點:
非常明顯的看到,主線程結(jié)束以后,子線程還沒有來得及執(zhí)行,整個程序就退出了。
三:join的作用
import threading
import time
def run():
time.sleep(2)
print('當前線程的名字是: ', threading.current_thread().name)
time.sleep(2)
if __name__ == '__main__':
start_time = time.time()
print('這是主線程:', threading.current_thread().name)
thread_list = []
for i in range(5):
t = threading.Thread(target=run)
thread_list.append(t)
for t in thread_list:
t.setDaemon(True)
t.start()
for t in thread_list:
t.join()
print('主線程結(jié)束了!' , threading.current_thread().name)
print('一共用時:', time.time()-start_time)
其執(zhí)行結(jié)果如下:

關(guān)鍵點:
可以看到,主線程一直等待全部的子線程結(jié)束之后,主線程自身才結(jié)束,程序退出。
主程序意外退出的情況
在線程A中使用B.join()表示線程A在調(diào)用join()處被阻塞,且要等待線程B的完成才能繼續(xù)執(zhí)行
import threading
import time
def child_thread1():
for i in range(10):
time.sleep(1)
print('child_thread1_running...')
def child_thread2():
for i in range(5):
time.sleep(1)
print('child_thread2_running...')
def parent_thread():
print('parent_thread_running...')
thread1 = threading.Thread(target=child_thread1)
thread2 = threading.Thread(target=child_thread2)
thread1.setDaemon(True)
thread2.setDaemon(True)
thread1.start()
thread2.start()
thread2.join()
1/0
thread1.join()
print('parent_thread_exit...')
if __name__ == "__main__":
parent_thread()
輸出:
parent_thread_running...
child_thread1_running...
child_thread2_running...
child_thread1_running...
child_thread2_running...
child_thread1_running...
child_thread2_running...
child_thread1_running...
child_thread2_running...
child_thread1_running...
child_thread2_running...
Traceback (most recent call last):
File "E:/test_thread.py", line 31, in <module>
parent_thread()
File "E:/test_thread.py", line 25, in parent_thread
1/0
ZeroDivisionError: integer division or modulo by zero
主線程在執(zhí)行到thread2.join()時被阻塞,等待thread2結(jié)束后才會執(zhí)行下一句
1/0會使主線程報錯退出,且thread1設置了daemon=True,因此主線程意外退出時thread1也會立即結(jié)束。thread1.join()沒有被主線程執(zhí)行
總結(jié)
到此這篇關(guān)于Python多線程以及多線程中join()使用的文章就介紹到這了,更多相關(guān)Python多線程join()的用法內(nèi)容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
相關(guān)文章
簡單了解Python write writelines區(qū)別
這篇文章主要介紹了簡單了解Python write writelines區(qū)別,文中通過示例代碼介紹的非常詳細,對大家的學習或者工作具有一定的參考學習價值,需要的朋友可以參考下2020-02-02
python heic后綴圖片文件轉(zhuǎn)換成jpg格式的操作
這篇文章主要介紹了python heic后綴圖片文件轉(zhuǎn)換成jpg格式的操作,具有很好的參考價值,希望對大家有所幫助。一起跟隨小編過來看看吧2021-03-03
Python?matplotlib的spines模塊實例詳解
作為程序員,經(jīng)常需要進行繪圖,下面這篇文章主要給大家介紹了關(guān)于Python?matplotlib的spines模塊的相關(guān)資料,文中通過實例代碼介紹的非常詳細,需要的朋友可以參考下2022-08-08
Python中parsel兩種獲取數(shù)據(jù)方式小結(jié)
本文主要介紹了Python中parsel兩種獲取數(shù)據(jù)方式小結(jié),文中通過示例代碼介紹的非常詳細,對大家的學習或者工作具有一定的參考學習價值,需要的朋友們下面隨著小編來一起學習學習吧2023-04-04

