2016-07-23 118 views
0

我正在學習python多線程和隊列。下面創建了一堆,通過隊列將數據傳遞到另一個線程進行打印線程:python多線程隊列沒有運行或乾淨地退出

import time 
import threading 
import Queue 

queue = Queue.Queue() 

def add(data): 
    return ["%sX" % x for x in data] 

class PrintThread(threading.Thread): 
    def __init__(self, queue): 
     threading.Thread.__init__(self) 
     self.queue = queue 

    def run(self): 
     data = self.queue.get() 
     print data 
     self.queue.task_done() 

class MyThread(threading.Thread): 
    def __init__(self, queue, data): 
     threading.Thread.__init__(self) 
     self.queue = queue 
     self.data = data 

    def run(self): 
     self.queue.put(add(self.data)) 

if __name__ == "__main__": 
    a = MyThread(queue, ["a","b","c"]) 
    a.start() 
    b = MyThread(queue, ["d","e","f"]) 
    b.start() 
    c = MyThread(queue, ["g","h","i"]) 
    c.start() 

    printme = PrintThread(queue) 
    printme.start() 

    queue.join() 

不過,我看只能從第一個線程打印出來的數據:再沒有什麼別的

['aX', 'bX', 'cX'] 

,但該程序不會退出。我必須殺死進程才能退出。

理想情況下,在每個MyThread執行數據處理並將結果放入隊列後,該線程應該退出?同時PrintThread應該採取任何隊列和打印它。

畢竟MyThread線程已經完成並且PrintThread線程已經完成處理隊列上的所有內容,程序應該乾淨地退出。

我做錯了什麼?

編輯

如果每個MyThread線程需要一段時間來處理,是有辦法保證PrintThread線程將等待所有的MyThread線程完成前,將退出本身?

這樣,打印線程肯定會處理隊列中的每個可能的數據,因爲所有其他線程已經退出。

例如,

class MyThread(threading.Thread): 
    def __init__(self, queue, data): 
     threading.Thread.__init__(self) 
     self.queue = queue 
     self.data = data 

    def run(self): 
     time.sleep(10) 
     self.queue.put(add(self.data)) 

上述修改將等待10秒鐘抹任何東西隊列之前。打印線程將運行,但我認爲它現在過早退出,因爲隊列中沒有數據,所以程序不打印任何內容。

回答

0

您的PrintThread不會循環,而是隻打印出一個隊列項目,然後停止運行。

因此,隊列將永遠是空的,queue.join()聲明將阻止主程序從終止

更改您的PrintThreadrun()方法爲以下代碼,以便使所有的隊列項處理:

try: 
    while True: 
     data = self.queue.get_nowait() 
     print data 
     self.queue.task_done() 
except queue.Empty: 
    # All items have been taken off the queue 
    pass 
+0

如何解決'MyThread'線程需要5秒以上處理的問題?例如,如果我們在'MyThread'的'run()'之後放置'time.sleep(20)',最終的結果是空的;沒有打印出來。有沒有辦法保證'PrintThread'是最後退出的線程?這樣,無論其他線程處理數據的時間如何,所有數據都保證在隊列中,並且PrintThread有機會處理它們。 – warchest

+0

您需要保持'PrintThread'運行,例如通過將其創建爲[守護線程](https://docs.python.org/3.5/library/threading.html#threading.Thread.daemon)。另一種方法是使用['threading.Event'](https://docs.python.org/3.5/library/threading.html#threading.Event)來指示線程停止主程序(如線程本身不知道是否期望更多的隊列中的項目)。 –

+0

我設置了'printme。setDaemon(True)',但該程序正在打印一些奇怪的輸出。例如,我看到像'['gX','hX'或'['aX','bX','cX'] ['gX',''這是一個問題嗎? – warchest