2016-08-19 61 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'哨兵可能之前的一些信件接收,從而既導致一些信件不被處理,但也陷入僵局,因爲進程試圖加入,即使隊列仍包含一些數據。但這是一個不同的問題。