1.了解Queue
Queue是python标准库中的线程安全的队列(FIFO)实现,提供了一个适用于多线程编程的先进先出的数据结构,即队列,用来在生产者和消费者线程之间的信息传递
|queue.Queue|先进先出队列|
|queue.LifoQueue|后进先出队列|
|queue.PriorityQueue|优先级队列|
|queue.deque|双线队列|
----------------------------------------------------------------------------------------
2.生产者和消费者模型
生产者和消费者模型
在并发编程中使用生产者和消费者模式能够解决绝大多数并发问题。该模式通过平衡生产线程和消费线程的工作能力来提高程序的整体处理数据的速度。
为什么要使用生产者和消费者模式
在线程世界里,生产者就是生产数据的线程,消费者就是消费数据的线程。在多线程开发当中,如果生产者处理速度很快,而消费者处理速度很慢,那么生产者就必须等待消费者处理完,才能继续生产数据。同样的道理,如果消费者的处理能力大于生产者,那么消费者就必须等待生产者。为了解决这个问题于是引入了生产者和消费者模式。
什么是生产者消费者模式
生产者消费者模式是通过一个容器来解决生产者和消费者的强耦合问题。生产者和消费者彼此之间不直接通讯,而通过阻塞队列来进行通讯,所以生产者生产完数据之后不用等待消费者处理,直接扔给阻塞队列,消费者不找生产者要数据,而是直接从阻塞队列里取,阻塞队列就相当于一个缓冲区,平衡了生产者和消费者的处理能力。
例子1
# ecoding=utf-8
import Queue
import threading,time
q = Queue.Queue(maxsize=10)
def Producer(name):
count =1
while True:
q.put("包子 %s" % count)
print "做了包子",count
count +=1
time.sleep(0.5)
def Consumer(name):
while True :
print "[%s] 取到[%s] 并且吃了它..." %(name,q.get())
time.sleep(1)
p = threading.Thread(target=Producer,args=("Lily",))
c = threading.Thread(target=Consumer,args=("Lilei",))
c1 = threading.Thread(target=Consumer,args=("Ahi",))
p.start()
c.start()
c1.start()
运行结果
做了包子 1
[Lilei] 取到[包子 1] 并且吃了它...
做了包子 2
[Ahi] 取到[包子 2] 并且吃了它...
做了包子 3
[Lilei] 取到[包子 3] 并且吃了它...
做了包子 4
[Ahi] 取到[包子 4] 并且吃了它...
做了包子 5[Lilei] 取到[包子 5] 并且吃了它...
做了包子 [Ahi] 取到[包子 6] 并且吃了它...
6
做了包子 7[Lilei] 取到[包子 7] 并且吃了它...
做了包子 8
[Ahi] 取到[包子 8] 并且吃了它...
做了包子 9
[Lilei] 取到[包子 9] 并且吃了它...
做了包子 10
[Ahi] 取到[包子 10] 并且吃了它...
做了包子 11
[Lilei] 取到[包子 11] 并且吃了它...
例子2
# ecoding=utf-8
from threading import current_thread, Thread
import time
import random
import queue
q = queue.Queue(5)
class Productor(Thread):
def run(self):
name = current_thread().getName()
nums = range(100)
while 1:
nowput = random.choice(nums)
if q.full(): # 消息队列满则停止生产
print "队列已经达到上限{0}".format(q.qsize())
time.sleep(10)
q.put(nowput)
print "生产者{0}生产了{1}".format(name, nowput)
sl = random.choice([1, 2, 3])
time.sleep(sl)
print "生产者休息了{0}秒".format(sl)
class Consumer(Thread):
def run(self):
name = current_thread().getName()
while 1:
if q.empty(): # 消息队列空的时候则暂停消费
print "队列空了,暂停消费"
time.sleep(5)
num = q.get()
q.task_done()
print "消费者{0}消费了{1}".format(name, num)
sl = random.choice([1, 2, 3])
time.sleep(sl)
print "消费者休息了{0}秒".format(sl)
if __name__ == '__main__':
p1 = Productor()
p1.start()
p2 = Productor()
p2.start()
c1 = Consumer()
c1.start()
c2 = Consumer()
c2.start()
c3 = Consumer()
c3.start()
运行结果
生产者Thread-1生产了90
生产者Thread-2生产了61
消费者Thread-3消费了90
消费者Thread-4消费了61
队列空了,暂停消费
消费者休息了1秒
队列空了,暂停消费
生产者休息了2秒
生产者Thread-1生产了30
消费者休息了2秒
消费者Thread-3消费了30
生产者休息了2秒
生产者Thread-2生产了15
消费者休息了1秒
消费者Thread-3消费了15
生产者休息了2秒
生产者Thread-1生产了11
生产者休息了2秒
生产者Thread-2生产了94
生产者休息了1秒
生产者Thread-1生产了18
消费者Thread-5消费了11
生产者休息了2秒消费者Thread-4消费了94
消费者休息了3秒
消费者Thread-3消费了18