標籤:display 訊號 close max 整數 簡單 gif 任務 next
Python中,隊列是線程間最常用的交換資料的形式。Queue模組是提供隊列操作的模組,雖然簡單易用,但是不小心的話,還是會出現一些意外。
建立一個“隊列”對象
import Queue
q = Queue.Queue(maxsize = 10)
Queue.Queue類即是一個隊列的同步實現。隊列長度可為無限或者有限。可通過Queue的建構函式的選擇性參數maxsize來設定隊列長度。如果maxsize小於1就表示隊列長度無限。
將一個值放入隊列中
q.put(10) put(item[, block[, timeout]])
將item放入隊列中。
- 如果可選的參數block為True且timeout為空白對象(預設的情況,阻塞調用,無逾時)。
- 如果timeout是個正整數,阻塞調用進程最多timeout秒,如果一直無空空間可用,拋出Full異常(帶逾時的阻塞調用)。
- 如果block為False,如果有空閑空間可用將資料放入隊列,否則立即拋出Full異常
其非阻塞版本為put_nowait等同於put(item, False)
將一個值從隊列中取出
q.get() get([block[, timeout]])
調用隊列對象的get()方法從隊頭刪除並返回一個項目。選擇性參數為block,預設為True。如果隊列為空白且block為True,get()就使調用線程暫停,直至有項目可用。如果隊列為空白且block為False,隊列將引發Empty異常。
從隊列中移除並返回一個資料。block跟timeout參數同put方法
其非阻塞方法為`get_nowait()`相當與get(False)
Python Queue模組有三種隊列及建構函式:
1、Python Queue模組的FIFO隊列先進先出。 class Queue.Queue(maxsize)
2、LIFO類似於堆,即先進後出。 class Queue.LifoQueue(maxsize)
3、還有一種是優先順序隊列層級越低越先出來。 class Queue.PriorityQueue(maxsize)
此包中的常用方法(q = Queue.Queue()):
q.qsize() 返回隊列的大小
q.empty() 如果隊列為空白,返回True,反之False
q.full() 如果隊列滿了,返回True,反之False
q.full 與 maxsize 大小對應
q.get([block[, timeout]]) 擷取隊列,timeout等待時間
q.get_nowait() 相當q.get(False)
非阻塞 q.put(item) 寫入隊列,timeout等待時間
q.put_nowait(item) 相當q.put(item, False)
q.task_done() 在完成一項工作之後,向任務已經完成的隊列發送一個訊號,每一個get()調用得到一個任務,接下來的task_done()調用告訴隊列該任務已經處理完畢。如果當前一個join()正在阻塞,它將在隊列中的所有任務都處理完時恢複執行(即每一個由put()調用入隊的任務都有一個對應的task_done()調用)。
q.join() 實際上意味著等到隊列為空白,再執行別的操作.阻塞調用線程,直到隊列中的所有任務被處理掉。
只要有資料被排入佇列,未完成的任務數就會增加。當消費者線程調用task_done()(意味著有消費者取得任務並完成任務),未完成的任務數就會減少。當未完成的任務數降到0,join()解除阻塞。
先進先出:
import Queueq = Queue.Queue(maxsize=5)for i in range(5): q.put(i)while not q.empty(): print q.get()
結果:
01234
View Code先進後出:
q = Queue.LifoQueue()for i in range(5): q.put(i)while not q.empty(): print q.get()
結果:
43210
View Code優先順序:
#優先順序隊列import Queueimport threadingclass Job(object): def __init__(self, priority, description): self.priority = priority self.description = description print ‘Job:‘,description return def __cmp__(self, other): #需要加上這個比較函數, return cmp(self.priority, other.priority) #Return negative if x<y, zero if x==y, positive if x>y.q = Queue.PriorityQueue()q.put(Job(3, ‘mid-level job‘))q.put(Job(10, ‘low-level job‘))q.put(Job(1, ‘high-level job‘))def process_job(q): while True: next_job = q.get() print ‘for:‘, next_job.description q.task_done()workers = [threading.Thread(target=process_job, args=(q,)), threading.Thread(target=process_job, args=(q,)) ]for w in workers: w.setDaemon(True) #守護進程 w.start()q.join()
View Code
運行結果:
Job: mid-level jobJob: low-level jobJob: high-level jobfor: high-level jobfor: mid-level jobfor: low-level job
View Code
複雜一點的
實現一個線程不斷產生一個隨機數到一個隊列中(考慮使用Queue這個模組)
實現一個線程從上面的隊列裡面不斷的取出奇數
實現另外一個線程從上面的隊列裡面不斷取出偶數
#!/usr/bin/python# coding=utf-8# __author__=‘dahu‘# data=2017-#import random, threading, timefrom Queue import Queue# Producer threadclass Producer(threading.Thread): def __init__(self, t_name, queue): # threading.Thread.__init__(self, name=t_name) super(Producer,self).__init__(name=t_name) #兩個都可以,傾向於這個 self.data = queue def run(self): for i in range(5): # 隨機產生10個數字 ,可以修改為任意大小 randomnum = random.randint(1, 20) print "%s: %s is producing %d to the queue!" % (time.ctime(), self.getName(), randomnum) self.data.put(randomnum) # 將資料依次存入隊列 time.sleep(1) print "%s: %s finished!" % (time.ctime(), self.getName())# Consumer threadclass Consumer_even(threading.Thread): def __init__(self, t_name, queue): # threading.Thread.__init__(self, name=t_name) super(Consumer_even, self).__init__(name=t_name) self.data = queue def run(self): while 1: try: val_even = self.data.get(1, 5) # get(self, block=True, timeout=None) ,1就是阻塞等待,5是逾時5秒 if val_even % 2 == 0: print "%s: %s is consuming. %d in the queue is consumed!" % (time.ctime(), self.getName(), val_even) time.sleep(2) else: self.data.put(val_even) time.sleep(2) except: # 等待輸入,超過5秒 就報異常 print "%s: %s finished!" % (time.ctime(), self.getName()) breakclass Consumer_odd(threading.Thread): def __init__(self, t_name, queue): threading.Thread.__init__(self, name=t_name) self.data = queue def run(self): while 1: try: val_odd = self.data.get(1, 5) if val_odd % 2 != 0: print "%s: %s is consuming. %d in the queue is consumed!" % (time.ctime(), self.getName(), val_odd) time.sleep(2) else: self.data.put(val_odd) time.sleep(2) except: print "%s: %s finished!" % (time.ctime(), self.getName()) break# Main threaddef main(): queue = Queue() producer = Producer(‘Pro.‘, queue) consumer_even = Consumer_even(‘Con_even.‘, queue) consumer_odd = Consumer_odd(‘Con_odd.‘, queue) producer.start() consumer_even.start() consumer_odd.start() producer.join() consumer_even.join() consumer_odd.join() print ‘All threads terminate!‘if __name__ == ‘__main__‘: main()
View Code
結果:
/usr/bin/python2.7 /home/dahu/PycharmProjects/SpiderLearning/request_lianxi/t9.queue.thread.pyTue Aug 22 16:12:25 2017: Pro. is producing 15 to the queue!Tue Aug 22 16:12:25 2017: Con_odd. is consuming. 15 in the queue is consumed!Tue Aug 22 16:12:26 2017: Pro. is producing 17 to the queue!Tue Aug 22 16:12:27 2017: Pro. is producing 2 to the queue!Tue Aug 22 16:12:27 2017: Con_odd. is consuming. 17 in the queue is consumed!Tue Aug 22 16:12:28 2017: Pro. is producing 15 to the queue!Tue Aug 22 16:12:29 2017: Con_even. is consuming. 2 in the queue is consumed!Tue Aug 22 16:12:29 2017: Con_odd. is consuming. 15 in the queue is consumed!Tue Aug 22 16:12:29 2017: Pro. is producing 18 to the queue!Tue Aug 22 16:12:30 2017: Pro. finished!Tue Aug 22 16:12:31 2017: Con_even. is consuming. 18 in the queue is consumed!Tue Aug 22 16:12:38 2017: Con_odd. finished!Tue Aug 22 16:12:38 2017: Con_even. finished!All threads terminate!Process finished with exit code 0
python Queue模組使用