前面不只一次提到,當程序中擁有多個線程時,主線程執行結束並不會影響子線程繼續執行。換句話說,只有程序中所有線程全部執行完畢后,程序才算真正結束。
下面程序演示了包含 2 個線程的程序執行流程:
1 import threading 2 3 #主線程執行如下語句 4 for i in range(5): 5 print(threading.current_thread().getName()) 6 7 #定義線程要調用的方法,*add可接收多個以非關鍵字方式傳入的參數 8 def action(*add): 9 for arc in add: 10 #調用 getName() 方法獲取當前執行該程序的線程名 11 print(threading.current_thread().getName() +" "+ arc) 12 #定義為線程方法傳入的參數 13 my_tuple = ("http://c.biancheng.net/python/",\ 14 "http://c.biancheng.net/shell/",\ 15 "http://c.biancheng.net/java/") 16 #創建線程 17 thread = threading.Thread(target = action,args =my_tuple) 18 #啟動線程 19 thread.start()
程序執行結果為:
MainThread MainThread MainThread MainThread MainThread Thread-1 http://c.biancheng.net/python/ Thread-1 http://c.biancheng.net/shell/ Thread-1 http://c.biancheng.net/java/
顯然,只有等 MatinThread 和 Thread-1 全部執行完之后,程序才執行結束。
除此之外,Python 還支持創建另一種線程,稱為守護線程(或后台線程)。此類線程的特點是,當程序中主線程及所有非守護線程執行結束時,未執行完畢的守護線程也會隨之消亡(進行死亡狀態),程序將結束運行。
Python 解釋器的垃圾回收機制就是守護線程的典型代表,當程序中所有主線程及非守護線程執行完畢后,垃圾回收機制也就沒有再繼續執行的必要了。
前面章節中,我們學習了 2 種創建線程的方式,守護線程本質也是線程,因此其創建方式和普通線程一樣,唯一不同之處在於,將普通線程設為守護線程,需通過線程對象調用其 damon 屬性,將該屬性的值該為 True。
並且需要注意的一點是,線程對象調用 daemon 屬性必須在調用 start() 方法之前,否則 Python 解釋器將報 RuntimeError 錯誤。
舉個例子,下面程序演示了如何創建一個守護線程:
import threading #定義線程要調用的方法,*add可接收多個以非關鍵字方式傳入的參數 def action(length): for arc in range(length): #調用 getName() 方法獲取當前執行該程序的線程名 print(threading.current_thread().getName()+" "+str(arc)) #創建線程 thread = threading.Thread(target = action,args =(20,)) #將thread設置為守護線程 thread.daemon = True #啟動線程 thread.start() #主線程執行如下語句 for i in range(5): print(threading.current_thread().getName())
程序中第 10 行代碼處,通過調用 thread 線程的 daemon 屬性並賦值為 True,則該 thread 線程就變成了守護線程。由於該程序中除了 thread 守護線程就只有主線程 MainThread,因此只要主線程執行結束,則守護線程將隨之消亡。程序執行結果為:
Thread-1 0 MainThread MainThread Thread-1 1 MainThread Thread-1 2 MainThread MainThread
