threading 模塊除了提供基本的線程和鎖定支持外,還提供了更高級別、功能更全面的線程管理。threading 模塊支持守護線程,其工做方式是:守護線程通常是一個等待客戶端請求的服務器,若是沒有客戶端請求,守護線程就是空閒的。若是把一個線程設置爲守護線程,就表示這個線程是不重要的,進程退出時不須要等待這個線程完成。(如何設置守護線程?只需執行賦值語句:
thread.daemon = True
)服務器
threading 模塊的對象:app
對象 | 描述 |
---|---|
Thread | 表示一個執行線程的對象 |
Lock | 鎖原語對象(和 thread 模塊中的鎖同樣) |
RLock | 可重入鎖對象,使單一線程能夠(再次)得到已持有的鎖(鎖遞歸) |
Condition | 條件變量對象,使得一個線程等待另外一個線程知足特定的「條件」,好比改變狀態或者某個數據 |
Event | 條件變量的通用版本,任意數量的線程等待某個事件的發生,在該事件發生後全部線程將被激活 |
Semaphore | 爲線程間共享的有限資源提供了一個「計數器」,若是沒有可用資源時會被阻塞 |
BoundedSemaphore | 與 Semaphore 類似,不過它不容許超過初始值 |
Timer | 與 Thread 類似, 不過它要在運行前等待一段時間 |
Barrier① | 建立一個「障礙」,必須達到指定數量的線程後才能夠繼續 |
threading 模塊的 Thread 類是主要的執行對象,它有 thread 模塊中沒有的不少函數。ide
Thread 對象的屬性和方法:函數
屬性/方法 | 描述 |
---|---|
Thread 對象數據屬性 | |
name | 線程名 |
ident | 線程的標識符 |
daemon | 布爾標誌,表示這個線程是不是守護線程 |
Thread 對象方法 | |
_init_(group=None, tatget=None, name=None, args=(), kwargs={}, verbose=None, daemon=None) | 實例化一個線程對象,須要有一個可調用的 target,以及其參數 args 或 kwargs 。還能夠傳遞 name 或 group 參數,不事後者還未實現。此外, verbose 標誌也是可接受的。 而 daemon 的值將會設定 thread.daemon 屬性/標誌 |
start() | 開始執行線程 |
run() | 定義線程功能的方法(一般在子類中被應用開發者重寫) |
join(timeout=None) | 直至啓動的線程終止以前一直掛起,除非給出了 timeout (單位爲秒),不然會一直阻塞 |
is_alive() | 布爾標誌,表示這個線程是否還存活 |
使用 Thread 類能夠有不少種方法建立線程,好比:oop
建立 Thread 的實例,傳給它一個函數;spa
建立 Thread 的實例,傳給它一個可調用的類實例;線程
派生 Thread 的子類,並建立子類的實例。code
*注:通常選擇第一個和第三個,當須要一個更加符合面向對象的接口時選擇第三個對象
使用 threading 模塊(mtsleepC.py):blog
*注:threading 模塊的 Thread 類中有個 join() 方法,可讓主線程等待全部線程執行完畢。
1 import threading 2 from time import sleep, ctime 3 4 loops = [4,2] 5 6 def loop(nloop, nsec): 7 print('start loop %s at:%s' % (nloop, ctime())) 8 sleep(nsec) 9 print('loop %s done at:%s' % (nloop, ctime())) 10 11 def main(): 12 print("starting at:%s" % ctime()) 13 threads = [] 14 nloops = range(len(loops)) 15 16 for i in nloops: 17 t = threading.Thread(target=loop, args=(i, loops[i])) 18 threads.append(t) 19 20 for i in nloops: 21 threads[i].start() 22 23 for i in nloops: 24 threads[i].join() 25 26 print('all DONE at:%s' % ctime()) 27 28 29 if __name__ == '__main__': 30 main()
運行後輸出結果:
1 $ mtsleepC.py 2 starting at:Mon Jul 23 12:44:48 2018 3 start loop 0 at:Mon Jul 23 12:44:48 2018 4 start loop 1 at:Mon Jul 23 12:44:48 2018 5 loop 1 done at:Mon Jul 23 12:44:50 2018 6 loop 0 done at:Mon Jul 23 12:44:52 2018 7 all DONE at:Mon Jul 23 12:44:52 2018
實例化每一個 Thread 對象時,把函數(target)和參數(args)傳進去,而後獲得返回的 Thread 實例。實例化 Thread 和調用 thread.start_new_thread() 的最大區別就是新線程不會當即執行。當全部線程分配完後,經過調用每一個線程的 start() 方法讓他們開始執行。join() 方法將等待線程結束,或者超過提供的時間自動結束。對 join() 方法而言,它根本不須要調用,一旦線程啓動它就會一直執行,直到給定的函數完成後退出。
使用可調用的類(mtsleepD.py):
*注:本例中將傳遞進去一個可調用類(實例)而不單單是一個函數。提供了更加面向對象的方法
1 import threading 2 from time import sleep, ctime 3 4 loops = [4,2] 5 6 class ThreadFunc(object): 7 8 def __init__(self, func, args, name=''): 9 self.name = name 10 self.func = func 11 self.args = args 12 13 def __call__(self): 14 self.func(*self.args) 15 16 def loop(nloop, nsec): 17 print('start loop %s at:%s' % (nloop, ctime())) 18 sleep(nsec) 19 print('loop %s done at:%s' % (nloop, ctime())) 20 21 def main(): 22 print('starting at:%s' % ctime()) 23 threads = [] 24 nloops = range(len(loops)) 25 26 for i in nloops: # 建立全部線程 27 t = threading.Thread( 28 target=ThreadFunc(loop, (i, loops[i]),loop.__name__) 29 ) 30 threads.append(t) 31 32 for i in nloops: # 啓動全部線程 33 threads[i].start() 34 35 for i in nloops: # 等待結束 36 threads[i].join() 37 38 print('all DONE at:%s' % ctime()) 39 40 41 if __name__ == '__main__': 42 main()
運行後的輸出結果:
1 $ mtsleepD.py 2 starting at:Tue Jul 24 09:02:32 2018 3 start loop 0 at:Tue Jul 24 09:02:32 2018 4 start loop 1 at:Tue Jul 24 09:02:32 2018 5 loop 1 done at:Tue Jul 24 09:02:34 2018 6 loop 0 done at:Tue Jul 24 09:02:36 2018 7 all DONE at:Tue Jul 24 09:02:36 2018
子類化的 Thread(mtsleepE.py):
*注:本例中將對 Thread 子類化,而不是直接對其實例化。這將使咱們在定製線程對象時擁有更多靈活性,也可以簡化線程建立的調用過程。
1 import threading 2 from time import sleep, ctime 3 4 loops = [4,2] 5 6 class MyThread(threading.Thread): 7 8 def __init__(self, func, args, name=''): 9 threading.Thread.__init__(self) 10 self.name = name 11 self.func = func 12 self.args = args 13 14 def run(self): 15 self.func(*self.args) 16 17 def loop(nloop, nsec): 18 print('start loop %s at:%s' % (nloop, ctime())) 19 sleep(nsec) 20 print('loop %s done at:%s' % (nloop, ctime())) 21 22 def main(): 23 print('starting at:%s' % ctime()) 24 threads = [] 25 nloops = range(len(loops)) 26 27 for i in nloops: # 建立全部線程 28 t = MyThread(loop, (i, loops[i]), loop.__name__) 29 threads.append(t) 30 31 for i in nloops: # 啓動全部線程 32 threads[i].start() 33 34 for i in nloops: # 等待結束 35 threads[i].join() 36 37 print('all DONE at:%s' % ctime()) 38 39 40 if __name__ == '__main__': 41 main()
運行後的輸出結果:
1 $ mtsleepE.py 2 starting at:Tue Jul 24 09:13:49 2018 3 start loop 0 at:Tue Jul 24 09:13:49 2018 4 start loop 1 at:Tue Jul 24 09:13:49 2018 5 loop 1 done at:Tue Jul 24 09:13:51 2018 6 loop 0 done at:Tue Jul 24 09:13:53 2018 7 all DONE at:Tue Jul 24 09:13:53 2018
函數 | 描述 |
---|---|
active_count() | 當前活動的 Thread 對象個數 |
current_thread | 返回當前活動的 Thread 對象 |
enumerate() | 返回當前活動的 Thread 對象列表 |
settrace(func) | 爲全部線程設置一個 trace 函數 |
setprofile(func) | 爲全部線程設置一個 profile 函數 |
stack_size(size=0) | 返回新建立線程的棧大小;或爲後續建立的線程設定棧的大小爲 size |