2016-08-19 36 views
1

在下面的代码中,如果我放入daemon = True,consumer将在读取所有队列条目之前退出。如果消费者不是守护进程,那么即使在所有条目的task_done()之后,主线程也总是被阻塞。JoinableQueue join()方法甚至在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

让我们来看看,我相信,这里发生的事情:

  1. 两个进程正在启动。
  2. consumer进程开始其循环并阻塞,直到从队列中接收到一个值。
  3. producer1进程用一个字母给队列提供26次,而主进程用一个数字给队列提供9次。不能保证字母或数字的输入顺序 - 一个数字可以很好地显示在一封信之前。
  4. producer1和主要流程都是在提供数据的情况下完成的,则队列正在连接。这里没问题,队列可以被连接,因为所有的缓冲数据都被消耗掉了,并且在每次读取之后调用task_done()
  5. 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'哨兵可能之前的一些信件接收,从而既导致一些信件不被处理,但也陷入僵局,因为进程试图加入,即使队列仍包含一些数据。但这是一个不同的问题。