以前咱們已經學會如何在代碼塊中建立新的線程去執行咱們要同步執行的多個任務,可是線程的世界遠不止如此。接下來,咱們要介紹的是整個threading模塊。threading基於Java的線程模型設計。鎖(Lock)和條件變量(Condition)在Java中是對象的基本行爲(每個對象都自帶了鎖和條件變量),而在Python中則是獨立的對象,因此python的threading模塊中還提供了Lock,Rlock,Condition,Event等經常使用類,它們在python中是獨立於Tread模塊的,可是卻與線程緊密相關,不可分割。html
須要注意的是:python的線程中沒有優先級、線程組,也不能被中止、暫停、恢復、中斷,線程只能隨着線程中的代碼執行完畢而被銷燬。查了n多資料以後終於接受了以上事實,我的以爲這是python的一個坑,致使了我在實現線程池的時候沒法中止已經注入了方法且執行超時的線程。python
threading模塊提供的類:
Thread, Lock, Rlock, Condition, [Bounded]Semaphore, Event, Timer, local.多線程
threading 模塊提供的經常使用方法:
threading.currentThread(): 返回當前的線程變量。
threading.enumerate(): 返回一個包含正在運行的線程的list。正在運行指線程啓動後、結束前,不包括啓動前和終止後的線程。
threading.activeCount(): 返回正在運行的線程數量,與len(threading.enumerate())有相同的結果。app
threading模塊經常使用類詳解ide
Thread類:咱們使用Thread類來建立新的線程學習
1 import time 2 import threading 3 4 def printNum(a): 5 print 'num:',a 6 time.sleep(1) 7 8 def ThreadTest(i): 9 return threading.Thread(target=printNum, args=(999,)) 10 11 thread_arr = [] 12 for i in range(10): 13 t = ThreadTest(i) 14 thread_arr.append(t) 15 16 for t in thread_arr: 17 t.start() 18 19 for t in thread_arr: 20 t.join() 21 22 print 'finished'
Lock類和Rlock類:因爲線程之間隨機調度:某線程可能在執行n條後,CPU接着執行其餘線程。爲了多個線程同時操做一個內存中的資源時不產生混亂,咱們使用鎖ui
不管是lock仍是rlock,提供的方法都很是簡單,acquire和release。可是rlock和lock的區別是什麼呢?RLock容許在同一線程中被屢次acquire。而Lock卻不容許這種狀況。注意:若是使用RLock,那麼acquire和release必須成對出現,即調用了n次acquire,必須調用n次的release才能真正釋放所佔用的鎖。spa
1 #!/usr/bin/env python 2 #-*-coding:utf-8-*- 3 __author__ = 'Eva_J' 4 5 import threading 6 lock = threading.Lock() #Lock對象 7 lock.acquire() 8 lock.acquire() #產生了死鎖。 9 lock.release() 10 lock.release() 11 12 13 import threading 14 rLock = threading.RLock() #RLock對象 15 rLock.acquire() 16 rLock.acquire() #在同一線程內,程序不會堵塞。 17 rLock.release() 18 rLock.release()
Condition類:條件變量對象能讓一個線程停下來,等待其它線程知足了某個「條件」。如,狀態的改變或值的改變。線程
比較經典的例子是下面這個生產者與消費者的例子,這個例子網上一搜處處都是,這裏簡單解釋一下這段代碼的意義,代碼中寫了兩個類,Consumer和Producer,分別繼承了Thread類,咱們分別初始化這兩個類得到了c和p對象,並啓動這兩個線程。則這兩個線程去執行run方法(這裏與Thread類內部的調度有關),定義了producer全局變量和condition對象爲全局變量,當producer不大於1時,消費者線程被condition對象阻塞,不能繼續消費(這裏是再也不遞減),當producer不小於10時,生產者線程被condition對象阻塞,再也不生產(這裏是再也不累加),代碼在下面,拿去執行,斷點一下就明白了。設計
1 #!/usr/bin/env python 2 #-*-coding:utf-8-*- 3 __author__ = 'Eva_J' 4 5 import threading 6 import time 7 8 condition = threading.Condition() 9 products = 0 10 11 class Producer(threading.Thread): 12 def __init__(self): 13 threading.Thread.__init__(self) 14 15 def run(self): 16 global condition, products 17 while True: 18 if condition.acquire(): 19 if products < 10: 20 products += 1; 21 print "Producer(%s):deliver one, now products:%s" %(self.name, products) 22 condition.notify() 23 else: 24 print "Producer(%s):already 10, stop deliver, now products:%s" %(self.name, products) 25 condition.wait(); 26 condition.release() 27 time.sleep(2) 28 29 class Consumer(threading.Thread): 30 def __init__(self): 31 threading.Thread.__init__(self) 32 33 def run(self): 34 global condition, products 35 while True: 36 if condition.acquire(): 37 if products > 1: 38 products -= 1 39 print "Consumer(%s):consume one, now products:%s" %(self.name, products) 40 condition.notify() 41 else: 42 print "Consumer(%s):only 1, stop consume, products:%s" %(self.name, products) 43 condition.wait(); 44 condition.release() 45 time.sleep(2) 46 47 if __name__ == "__main__": 48 for p in range(0, 2): 49 p = Producer() 50 p.start() 51 52 for c in range(0, 10): 53 c = Consumer() 54 c.start()
Event類:通用的條件變量。多個線程能夠等待某個事件的發生,在事件發生後,全部的線程都會被激活。
這是一個比較關鍵的類,我在寫線程池的時候看到python的threadpool模塊也用到了。它的意義在於能夠控制屬於同一個線程類的多個實例化對象,讓他們同時阻塞或者執行。配合隊列來實現一個線程池很是好用。在接下里的博客中咱們還要繼續介紹。先放一個小例子在這裏練練手,瞭解一下event的用法。
1 #!/usr/bin/env python 2 #-*-coding:utf-8-*- 3 __author__ = 'Eva_J' 4 5 import threading 6 import time 7 8 event = threading.Event() 9 10 def func(): 11 # 等待事件,進入等待阻塞狀態 12 print '%s wait for event...' % threading.currentThread().getName() 13 event.wait() 14 15 # 收到事件後進入運行狀態 16 print '%s recv event.' % threading.currentThread().getName() 17 18 t1 = threading.Thread(target=func) 19 t2 = threading.Thread(target=func) 20 t1.start() 21 t2.start() 22 23 time.sleep(2) 24 25 # 發送事件通知 26 print 'MainThread set event.' 27 event.set()
參考文獻:
python多線程學習小結:http://www.myexception.cn/perl-python/1688021.html
python線程指南:http://www.cnblogs.com/huxi/archive/2010/06/26/1765808.html
threading.RLock和threading.Lock:http://blog.sina.com.cn/s/blog_5dd2af0901012rad.html
python的進程、線程與協程:http://www.cnblogs.com/wupeiqi/articles/5040827.html