方法介绍
JoinableQueue([maxsize])
创建可连接的共享进程队列。这就像是一个Queue对象,但队列允许项目的使用者通知生产者项目已经被成功处理。通知进程是使用共享的信号和条件变量来实现的。
JoinableQueue的实例p除了与Queue对象相同的方法之外,还具有以下方法:
- q.task_done()
- 使用者使用此方法发出信号,表示q.get()返回的项目已经被处理。如果调用此方法的次数大于从队列中删除的项目数量,将引发ValueError异常。用于消费者,是指每消费队列中的一个数据,就给join返回一个标识
- q.join()
- 生产者将使用此方法进行阻塞,直到队列中所有项目均被处理。阻塞将持续到为队列中的每个项目均调用q.task_done()方法为止。
- 下面的例子说明如何建立永远运行的进程,使用和处理队列上的项目。生产者将项目放入队列,并等待它们被处理。用于生产者,等待 task_done的返回结果,生产者就获得消费者当前消费了多少个数据
import os,time
from multiprocessing import Process,JoinableQueue
def producer(name,q):
for i in range(10):
res = '%s%s'%(name,i)
q.put(res)
print('\033[45m %s生产了 %s\033[0m'%(os.getpid(),res))
q.join()
def consumer(q):
while True:
res = q.get()
print('\033[46m%s 吃 %s\033[0m' % (os.getpid(), res))
q.task_done() # 向q.join()发送一次信号,证明一个数据已经被取走了
if __name__ == '__main__':
q=JoinableQueue()
#生产者们:即厨师们
p1=Process(target=producer,args=('rose',q))
p2=Process(target=producer,args=('波姐',q))
p3=Process(target=producer,args=('老王',q))
#消费者们:即吃货们
c1=Process(target=consumer,args=(q,))
c2=Process(target=consumer,args=(q,))
c2.daemon = True
c1.daemon = True #这个要放在启动进程前面代表p.daemon:.
# 默认值为False,如果设为True,代表p为后台运行的守护进程,当p的父进程终止时,
# p也随之终止,并且设定为True后,p不能创建自己的新进程,必须在p.start()之前设置
#开始
p_l=[p1,p2,p3,c1,c2]
for p in p_l:
p.start()
# p1.join()
# p2.join()
# p3.join()
# c1.start()
# c2.start()
time.sleep(2) #加上时间让子进程执行完
print('主')
结果:
3054生产了 rose0
3054生产了 rose1
3054生产了 rose2
3054生产了 rose3
3054生产了 rose4
3054生产了 rose5
3054生产了 rose6
3054生产了 rose7
3054生产了 rose8
3054生产了 rose9
主
3057生产了 老王0
3057生产了 老王1
3057生产了 老王2
3057生产了 老王3
3057生产了 老王4
3057生产了 老王5
3057生产了 老王6
3057生产了 老王7
3057生产了 老王8
3057生产了 老王9
3059 吃 rose0
3055生产了 波姐0
3055生产了 波姐1
3055生产了 波姐2
3055生产了 波姐3
3055生产了 波姐4
3055生产了 波姐5
3055生产了 波姐6
3055生产了 波姐7
3055生产了 波姐8
3055生产了 波姐9
3058 吃 rose1
3058 吃 rose2
3058 吃 rose3
3058 吃 rose4
3058 吃 rose5
3058 吃 rose6
3058 吃 rose7
3058 吃 rose8
3058 吃 rose9
3058 吃 老王0
3058 吃 老王1
3058 吃 老王2
3058 吃 老王3
3058 吃 老王4
3058 吃 老王5
3058 吃 老王6
3058 吃 老王7
3058 吃 老王8
3058 吃 老王9
3058 吃 波姐0
3058 吃 波姐1
3058 吃 波姐2
3058 吃 波姐3
3058 吃 波姐4
3058 吃 波姐5
3058 吃 波姐6
3058 吃 波姐7
3058 吃 波姐8
3058 吃 波姐9
主进程等--->p1,p2,p3等---->c1,c2 41
p1,p2,p3结束了,证明c1,c2肯定全都收完了p1,p2,p3发到队列的数据
因而c1,c2也没有存在的价值了,不需要继续阻塞在进程中影响主进程了。应该随着主进程的结束而结束,所以设置成守护进程就可以了。