队列&生产者消费者

Queue是python标准库中的线程安全的队列(FIFO)实现,提供了一个适用多线程的先进先出的数据结构,即队列,用来在生产者和消费者线程之间信息传递.

如果在多线程中,给存放数据,也就是修改同一份数据, 所以就需要上锁   但是在列队这不用加

因为!!队列是线程安全的,存储数据的时候,程序就会给上锁,  能够保证数据的唯一性.

1.先入先出  fisrt in fisrt out  ---> queue.Queue()           FIFO队列

2.后入先出  last in fisrt out  ----> queue.LifoQueue()   LIFO队列

3.优先级队列           ----->queue.PriorityQueue()

 1 import queue
 2 
 3 ###先进先出
 4 q1=queue.Queue(maxsize=3)          #这里设置是可以存放多少个队列  如果设置了3个 但是q.put达到3个以上  ,就会阻塞  因为这是队列 先进先出
 5 q1.put(1)
 6 q1.put(2)
 7 q1.put(3)
 8 
 9 ###权重 优先级
10 q2=queue.PriorityQueue()
11 q2.put([6,'alex'])
12 q2.put([3,'zhaichaoqun'])
13 q2.put([10,'renchenghon'])
14 
15 ###后进先出
16 q3=queue.LifoQueue()
17 q3.put([6,'alex'])
18 q3.put([3,'zhaichaoqun'])
19 q3.put([10,'renchenghon'])
20 
21 
22 print(q1.empty()) #判断是不是为空   不空为False
23 print(q1.full())    #判断是不是满
24 print(q1.qsize())  #队列大小
25 
26 #因为是队列  不能跳着取。 必须一个一个取 遵循先进先出
27 print(q1.get())  #get是用来取第一个值   并在队列中取消这个
28 print(q1.get())  #get是用来取第二个值
29 print(q1.get())  #get是用来取第三个值
30 print('取完后队列',q1.qsize())
31 
32 print(q2.get())
33 print(q2.get())
34 print(q2.get())
35  #这里get  如果没有值 就一直等待
36 print('---')
37 print(q3.get())
38 print(q3.get())
39 print(q3.get())

  q1.empty()  判断是不是为空

  q1.full() 判断队列是不是满了    #如果满了。在往队列中放数据就会卡住.

  q1.qsize() 队列大小

生产者消费者

来段实例代码看看

import queue
import time
import threading

def consumer(name):  #这就是定义的消费者。。。。   因为去q.get 队列中的值
    while True:
        print('%s 取得蛋糕 %s并吃了它' %(name,q.get()))   #q.get 就是去队列中取值
        time.sleep(0.5)
        q.task_done()  #回执
def produce(name):
    count=0
    #while q.qsize() <5:  #因为队列设置的大小为4  那么这里设置小于5,因为上面会取。队列就会取,所以这里会一直进行下去
    for i in range(10):
        print("%s生产了%s个蛋糕" %(name,count))
        q.put(count)
        count +=1
        #time.sleep(2)
    q.join()   #直到队列被消费完毕  
    print('生产完了------')
q=queue.Queue(maxsize=4) #设置队列大小为4
#创建线程
p1=threading.Thread(target=consumer,args=('rch',))
p2=threading.Thread(target=produce,args=('zcq',))
p1.start()
p2.start()

consumer 定义的消费者

produce 定义的生产者

这里有个点要记下:

  1.这里用到了q.task_done()  

    A。这里的作用是,每个消费者在消费完这个任务之后, 都要给你的生产者发送一个回执,生产者收集完所有的回执,就会判断所有的任务是不是都运行结束了,如果是,就可以结束了

    B。这里用到了join  ,跟前面是一样的,  这里就是等待所有子线程回执都回来, 才运行主线程.

这里可以一直增加生产者,或者消费者  。

生产者消费者的2个主要作用

1.程序的解耦合

2.提高了程序的运行效率

 

task_done()

 

意味着之前入队的一个任务已经完成。由队列的消费者线程调用。每一个get()调用得到一个任务,接下来的task_done()调用告诉队列该任务已经处理完毕。

 

如果当前一个join()正在阻塞,它将在队列中的所有任务都处理完时恢复执行(即每一个由put()调用入队的任务都有一个对应的task_done()调用)。

 

join()

 

阻塞调用线程,直到队列中的所有任务被处理掉。

 

只要有数据被加入队列,未完成的任务数就会增加。当消费者线程调用task_done()(意味着有消费者取得任务并完成任务),未完成的任务数就会减少。当未完成的任务数降到0,join()解除阻塞。

 

put(item[, block[, timeout]])

 

将item放入队列中。

 

  1. 如果可选的参数block为True且timeout为空对象(默认的情况,阻塞调用,无超时)。
  2. 如果timeout是个正整数,阻塞调用进程最多timeout秒,如果一直无空空间可用,抛出Full异常(带超时的阻塞调用)。
  3. 如果block为False,如果有空闲空间可用将数据放入队列,否则立即抛出Full异常

 

其非阻塞版本为put_nowait等同于put(item, False)

 

get([block[, timeout]])

 

从队列中移除并返回一个数据。block跟timeout参数同put方法

 

其非阻塞方法为`get_nowait()`相当与get(False)

 

empty()

 

如果队列为空,返回True,反之返回False

 

posted @ 2016-12-13 19:54  所有的梦想都画在墙上  阅读(219)  评论(0编辑  收藏  举报