告诉消费者多个生产者没有更多的结果

时间:2014-03-28 15:14:16

标签: python multiprocessing

我有一些代码可以将工作添加到一个队列,由多个工作人员处理,然后将结果放入另一个队列,由最终工作人员处理。当我有多个生产者向此结果队列添加材料时,如何可靠地向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)

1 个答案:

答案 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()

粗糙的代码,完全未经测试,但应该明白这一点。