初識python多執行緒
1) 在python中如何建立一個執行緒物件?
如果你要建立一個執行緒物件,很簡單,只要你的類繼承threading.Thread,然後在__init__裡首先呼叫threading.Thread的__init__方法即可:
-
import threading
-
class MyThread(threading.Thread):
-
def __init__(self,threadname):
-
threading.Thread.__init__(self,name=threadname)
這才僅僅是個空執行緒,我可不是要他拉空車的,他可得給我乾點實在活。很簡單,重寫類的run()方法即可,把你要線上程執行時做的事情都放到裡面
-
import threading,time
-
class MyThread(threading.Thread):
-
def __init__(self,threadname):
-
threading.Thread.__init__(self,name=threadname)
-
def run(self):
-
'''
-
run 方法
-
'''
-
for i in xrange(10):
-
print self.getName,i
-
time.sleep(1)
以上程式碼如果被執行之後會每隔1秒輸出一次資訊到螢幕,10次後結束。其中這裡getName()是threading.Thread類的一個方法,用來獲得這個執行緒物件的name。還有一個方法setName()當然就是來設定這個執行緒物件的name的了。
如果要建立一個執行緒,首先就要先建立一個執行緒物件
my = MyThread('test')
一個執行緒物件被建立後,他就處於“born”(誕生狀態),如何讓這個執行緒物件開始執行呢?只要呼叫執行緒物件的start()方法即可
-
import threading,time
-
class MyThread(threading.Thread):
-
def __init__(self,threadname):
-
threading.Thread.__init__(self,name=threadname)
-
def run(self):
-
for i in xrange(10):
-
print self.getName(),i
-
time.sleep(1)
-
my = MyThread('test')
-
my.start()
現線上程就處於“ready”狀態或者也稱為“runnable”狀態。
奇怪嗎?不是已經start了嗎?為什麼不稱為“running”狀態呢?其實是有原因的。因為我們的計算機一般是不具有真正並行處理能力的。我們所謂的多執行緒只是把時間分成片段,然後隔一個時間段就讓一個執行緒執行一下,然後進入“sleeping ”狀態,然後喚醒另一個在“sleeping”的執行緒,如此迴圈runnable->sleeping->runnable... ,只是因為計算機執行速度很快,而時間片段間隔很小,我們感受不到,以為是同時進行的。所以說一個執行緒在start了之後只是處在了可以執行的狀態,他什麼時候執行還是由系統來進行排程的。
那一個執行緒什麼時候會“dead”呢?一般來說當執行緒物件的run方法執行結束或者在執行中丟擲異常的話,那麼這個執行緒就會結束了。系統會自動對“dead”狀態執行緒進行清理。
如果一個執行緒A在執行的過程中需要等待另一個執行緒tB執行結束後才能執行的話,那就可以在A在呼叫B的B.join()方法,另外還可以給join()傳入等待的時間。
執行緒物件的setDaemon()方法可以讓子執行緒隨著主執行緒的退出而結束,不過注意的是setDaemon()方法必須線上程物件沒有呼叫start()方法之前呼叫(預設情況下;在python中,主執行緒結束後,會預設等待子執行緒結束後,主執行緒才退出)。
-
t1 = MyThread('t1')
-
print t1.getName(),t1.isDaemon()
-
t1.setDaemon(True)
-
print t1.getName(),t1.isDaemon()
-
t1.start()
-
print 'main thread exit'
當執行到 print 'main thread exit' 後,主執行緒就退出了,當然t1這個執行緒也跟著結束了。但是如果不使用t1執行緒物件的setDaemon()方法的話,即便主執行緒結束了,還要等待t1執行緒自己結束才能退出程序。isDaemon()是用來獲得一個執行緒物件的Daemonflag狀態的
如何來獲得與執行緒有關的資訊呢?
獲得當前正在執行的執行緒的引用
running = threading.currentThread()
獲得當前所有活動物件(即run方法開始但是未終止的任何執行緒)的一個列表
threadlist = threading.enumerate()
獲得這個列表的長度
threadcount = threading.activeCount()
檢視一個執行緒物件的狀態呼叫這個執行緒物件的isAlive()方法,返回1代表處於“runnable”狀態且沒有“dead”
threadflag = threading.isAlive()
2) 執行緒同歩佇列?
我們經常會採用生產者/消費者關係的兩個執行緒來處理一個共享緩衝區的資料。例如一個生產者執行緒接受使用者資料放入一個共享緩衝區裡,等待一個消費者執行緒對資料 取出處理。但是如果緩衝區的太小而生產者和消費者兩個非同步執行緒的速度不同時,容易出現一個執行緒等待另一個情況。為了儘可能的縮短共享資源並以相同速度工作 的各執行緒的等待時間,我們可以使用一個“佇列”來提供額外的緩衝區。
建立一個“佇列”物件
-
import Queue
-
myqueue = Queue.Queue(maxsize = 10)
Queue.Queue類即是一個佇列的同步實現。佇列長度可為無限或者有限。可通過Queue的建構函式的可選引數maxsize來設定佇列長度。如果maxsize小於1就表示佇列長度無限。
將一個值放入佇列中
myqueue.put(10)
呼叫佇列物件的put()方法在隊尾插入一個專案。put()有兩個引數,第一個item為必需的,為插入專案的值;第二個block為可選引數,預設為1。如果隊列當前為空且block為1,put()方法就使呼叫執行緒暫停,直到空出一個數據單元。如果block為0,put方法將引發Full異常。
將一個值從佇列中取出
myqueue.get()
呼叫佇列物件的get()方法從隊頭刪除並返回一個專案。可選引數為block,預設為1。如果佇列為空且block為1,get()就使呼叫執行緒暫停,直至有專案可用。如果block為0,佇列將引發Empty異常。
另外: q.task_done():表示q.get()返回的專案已被處理; q.join():表示直到佇列中所有專案均被處理。
參考自https://blog.csdn.net/a921800467b/article/details/8579915