我有一些代码可以将工作添加到一个队列,由多个工作人员处理,然后将结果放入另一个队列,由最终工作人员处理。当我有多个生产者向此结果队列添加材料时,如何可靠地向collector
进程发出信号,表示没有其他内容需要处理?
import multiprocessing
import time
J = multiprocessing.Queue()
R = multiprocessing.Queue()
def intermediate_worker(jobs, results):
while True:
task = jobs.get()
if task is None:
jobs.put(None)
break
print 'working', task
results.put(task)
def collector(result_queue) :
total = 0
while True :
result = result_queue.get()
total += result
print 'collection', total
[multiprocessing.Process(target=intermediate_worker, args=(J,R)).start()
for i in xrange(2)]
multiprocessing.Process(target=collector, args=(R,)).start()
for chunk_dummy in xrange(10) :
J.put(chunk)
J.put(None)
答案 0 :(得分:2)
有几种方法。一种是寻找 n 毒丸,其中 n 是你拥有的生产者数量。您已熟悉此方法,因为您正在使用它关闭生产者。这项工作没问题,但有点笨拙 - 你需要消费者额外的逻辑来跟踪你已经看过多少毒丸。
我个人最喜欢的是使用Semaphore
为我做计数。如果我们知道有多少生产者还活着,那么这就足以确定何时关闭消费者 - 我们会在(no producers are alive)
和(the queue is empty)
时将其关闭。
J = multiprocessing.Queue()
R = multiprocessing.Queue()
S = multiprocessing.Semaphore(NUMWORKERS)
def intermediate_worker(jobs, results, sem):
with sem: #context manager handles incrementing/decrementing the semaphore
while True:
task = jobs.get()
if task is None:
jobs.put(None)
break
print 'working', task
results.put(task)
def collector(result_queue, sem) :
total = 0
while sem.get_value() < NUMWORKERS or not result_queue.empty():
result = result_queue.get()
total += result
print 'collection', total
[multiprocessing.Process(target=intermediate_worker, args=(J,R,S)).start()
for i in xrange(NUMWORKERS)]
multiprocessing.Process(target=collector, args=(R,S)).start()
粗糙的代码,完全未经测试,但应该明白这一点。