在下面的代码中,如果我放daemon = True
,则在读取所有队列条目之前,使用者将退出。如果使用者是非守护进程,则即使在所有条目的task_done()
之后,主线程也始终被阻止。
from multiprocessing import Process, JoinableQueue
import time
def consumer(queue):
while True:
final = queue.get()
print (final)
queue.task_done()
def producer1(queue):
for i in "QWERTYUIOPASDFGHJKLZXCVBNM":
queue.put(i)
if __name__ == "__main__":
queue = JoinableQueue(maxsize=100)
p1 = Process(target=consumer, args=((queue),))
p2 = Process(target=producer1, args=((queue),))
#p1.daemon = True
p1.start()
p2.start()
print(p1.is_alive())
print (p2.is_alive())
for i in range(1, 10):
queue.put(i)
time.sleep(0.01)
queue.join()
答案 0 :(得分:0)
让我们看看 - 我相信 - 在这里发生了什么:
consumer
进程开始循环并阻塞,直到从队列中收到一个值。producer1
进程使用字母为队列提供26次,而主进程使用数字向队列提供9次。不保证字母或数字的输入顺序 - 在一封信之前可以很好地显示一个数字。producer1
和主进程都完成了提供数据时,队列正在加入。没问题,队列可以加入,因为所有缓冲的数据都已被使用,每次读取后都调用了task_done()
。consumer
进程仍在运行但被阻止,直到显示更多要消耗的数据。查看您的代码,我相信您将加入流程的概念与加入队列的概念相混淆。你最想要的是加入流程,你可能根本不需要一个可连接的队列。
#!/usr/bin/env python3
from multiprocessing import Process, Queue
import time
def consumer(queue):
for final in iter(queue.get, 'STOP'):
print(final)
def producer1(queue):
for i in "QWERTYUIOPASDFGHJKLZXCVBNM":
queue.put(i)
if __name__ == "__main__":
queue = Queue(maxsize=100)
p1 = Process(target=consumer, args=((queue),))
p2 = Process(target=producer1, args=((queue),))
p1.start()
p2.start()
print(p1.is_alive())
print(p2.is_alive())
for i in range(1, 10):
queue.put(i)
time.sleep(0.01)
queue.put('STOP')
p1.join()
p2.join()
同样,您的producer1
在提供所有字母后自行退出,但您需要一种方法告诉您的consumer
进程退出,因为它不再需要处理的数据。你可以通过发送一个哨兵来做到这一点,在这里我选择了字符串'STOP'
,但它可以是任何东西。
事实上,这段代码不是很好,因为在某些字母之前可能会收到'STOP'
哨兵,因此两者都会导致某些字母无法处理,但也会导致死锁,因为即使队列正在尝试加入进程仍然包含一些数据。但这是一个不同的问题。