一、隊列(Queue)
Python的Queue模塊中提供了同步的、線程安全的隊列類,包括FIFO(先入先出)隊列Queue,LIFO(后入先出)隊列LifoQueue,和優先級隊列PriorityQueue。這些隊列都實現了鎖原語,能夠在多線程中直接使用。可以使用隊列來實現線程間的同步。
常用方法:
- Queue.qsize() 返回隊列的大小
- Queue.empty() 如果隊列為空,返回True,反之False
- Queue.full() 如果隊列滿了,返回True,反之False,Queue.full 與 maxsize 大小對應
- Queue.get([block[, timeout]])獲取隊列,timeout等待時間
- Queue.get_nowait() 相當於Queue.get(False),非阻塞方法
- Queue.put(item) 寫入隊列,timeout等待時間
- Queue.task_done() 在完成一項工作之后,Queue.task_done()函數向任務已經完成的隊列發送一個信號。每個get()調用得到一個任務,接下來task_done()調用告訴隊列該任務已經處理完畢。
- Queue.join() 實際上意味着等到隊列為空,再執行別的操作
示例代碼如下:
-
from Queue import Queue,LifoQueue,PriorityQueue
-
#先進先出隊列
-
q=Queue(maxsize= 5)
-
#后進先出隊列
-
lq=LifoQueue(maxsize= 6)
-
#優先級隊列
-
pq=PriorityQueue(maxsize= 5)
-
-
for i in range(5):
-
q.put(i)
-
lq.put(i)
-
pq.put(i)
-
-
print "先進先出隊列:%s;是否為空:%s;多大,%s;是否滿,%s" %(q.queue,q.empty(),q.qsize(),q.full())
-
print "后進先出隊列:%s;是否為空:%s;多大,%s;是否滿,%s" %(lq.queue,lq.empty(),lq.qsize(),lq.full())
-
print "優先級隊列:%s;是否為空:%s,多大,%s;是否滿,%s" %(pq.queue,pq.empty(),pq.qsize(),pq.full())
-
-
print q.get(),lq.get(),pq.get()
-
-
print "先進先出隊列:%s;是否為空:%s;多大,%s;是否滿,%s" %(q.queue,q.empty(),q.qsize(),q.full())
-
print "后進先出隊列:%s;是否為空:%s;多大,%s;是否滿,%s" %(lq.queue,lq.empty(),lq.qsize(),lq.full())
-
print "優先級隊列:%s;是否為空:%s,多大,%s;是否滿,%s" %(pq.queue,pq.empty(),pq.qsize(),pq.full())
-
先進先出隊列:deque([0, 1, 2, 3, 4]);是否為空:False;多大,5;是否滿,True
-
后進先出隊列:[0, 1, 2, 3, 4];是否為空:False;多大,5;是否滿,False
-
優先級隊列:[0, 1, 2, 3, 4];是否為空:False,多大,5;是否滿,True
-
0 4 0
-
先進先出隊列:deque([1, 2, 3, 4]);是否為空:False;多大,4;是否滿,False
-
后進先出隊列:[0, 1, 2, 3];是否為空:False;多大,4;是否滿,False
-
優先級隊列:[1, 3, 2, 4];是否為空:False,多大,4;是否滿,False
還有一種隊列是雙邊隊列,示例代碼如下:
-
from Queue import deque
-
dq=deque([ 'a','b'])
-
dq.append( 'c')
-
print dq
-
print dq.pop()
-
print dq
-
print dq.popleft()
-
print dq
-
dq.appendleft( 'd')
-
print dq
-
print len(dq)
-
deque(['a', 'b', 'c'])
-
c
-
deque(['a', 'b'])
-
a
-
deque(['b'])
-
deque(['d', 'b'])
-
2
二、生產者消費者模式
生產者消費者模式並不是GOF提出的眾多模式之一,但它依然是開發同學編程過程中最常用的一種模式
生產者模塊兒負責產生數據,放入緩沖區,這些數據由另一個消費者模塊兒來從緩沖區取出並進行消費者相應的處理。該模式的優點在於:
- 解耦:緩沖區的存在可以讓生產者和消費者降低互相之間的依賴性,一個模塊兒代碼變化,不會直接影響另一個模塊兒
- 並發:由於緩沖區,生產者和消費者不是直接調用,而是兩個獨立的並發主體,生產者產生數據之后把它放入緩沖區,就繼續生產數據,不依賴消費者的處理速度
三、采用生產者消費者模式開發的Python多線程
在Python中,隊列是最常用的線程間的通信方法,因為它是線程安全的,自帶鎖。而Condition等需要額外加鎖的代碼操作,在編程對死鎖現象要很小心,Queue就不用擔心這個問題。
Queue多線程代碼示例如下:
-
from Queue import Queue
-
import time,threading
-
q=Queue(maxsize= 0)
-
-
def product(name):
-
count= 1
-
while True:
-
q.put( '氣球兵{}'.format(count))
-
print ('{}訓練氣球兵{}只'.format(name,count))
-
count+= 1
-
time.sleep( 5)
-
def consume(name):
-
while True:
-
print ('{}使用了{}'.format(name,q.get()))
-
time.sleep( 1)
-
q.task_done()
-
t1=threading.Thread(target=product,args=( 'wpp',))
-
t2=threading.Thread(target=consume,args=( 'ypp',))
-
t3=threading.Thread(target=consume,args=( 'others',))
-
-
t1.start()
-
t2.start()
-
t3.start()
網上還有很多非常好的生產者消費者模式的Queue代碼例子,開發同學需要根據具體的實際需求去設計實際模式