threading模塊—Python多線程編程

Threading 模塊

threading 模塊除了提供基本的線程和鎖定支持外,還提供了更高級別、功能更全面的線程管理。threading 模塊支持守護線程,其工做方式是:守護線程通常是一個等待客戶端請求的服務器,若是沒有客戶端請求,守護線程就是空閒的。若是把一個線程設置爲守護線程,就表示這個線程是不重要的,進程退出時不須要等待這個線程完成。(如何設置守護線程?只需執行賦值語句: thread.daemon = True )服務器

threading 模塊的對象:app

對象 描述
Thread 表示一個執行線程的對象
Lock 鎖原語對象(和 thread 模塊中的鎖同樣)
RLock 可重入鎖對象,使單一線程能夠(再次)得到已持有的鎖(鎖遞歸)
Condition 條件變量對象,使得一個線程等待另外一個線程知足特定的「條件」,好比改變狀態或者某個數據
Event 條件變量的通用版本,任意數量的線程等待某個事件的發生,在該事件發生後全部線程將被激活
Semaphore 爲線程間共享的有限資源提供了一個「計數器」,若是沒有可用資源時會被阻塞
BoundedSemaphore 與 Semaphore 類似,不過它不容許超過初始值
Timer 與 Thread 類似, 不過它要在運行前等待一段時間
Barrier 建立一個「障礙」,必須達到指定數量的線程後才能夠繼續
[ ①]  Python 3.2版本中引入

 

Thread 類

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

    *注:通常選擇第一個和第三個,當須要一個更加符合面向對象的接口時選擇第三個對象

建立 Thread 的實例,傳給它一個函數

使用 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() 方法而言,它根本不須要調用,一旦線程啓動它就會一直執行,直到給定的函數完成後退出。

 

建立 Thread 的實例,傳給它一個可調用的類實例

使用可調用的類(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 的子類,並建立子類的實例

子類化的 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

 

 

threading 模塊的其它函數

函數 描述
active_count() 當前活動的 Thread 對象個數
current_thread 返回當前活動的 Thread 對象
enumerate() 返回當前活動的 Thread 對象列表
settrace(func) 爲全部線程設置一個 trace 函數
setprofile(func) 爲全部線程設置一個 profile 函數
stack_size(size=0) 返回新建立線程的棧大小;或爲後續建立的線程設定棧的大小爲 size
相關文章
相關標籤/搜索