2016-08-02 43 views
4

我的代碼如下,主線程中的queue.join()調用對非主線程有什麼作用?

import time, queue, threading 

def washer(dishes, dish_queue): 
    for dish in dishes: 
     print ("Washing", dish) 
     time.sleep(1) 
     dish_queue.put(dish) 

def dryer(dish_queue): 
    while True: 
     dish = dish_queue.get() 
     print("Drying", dish) 
     time.sleep(2) 
     dish_queue.task_done() 
     print('dryer') 

dish_queue = queue.Queue() 
for n in range(2): 
    dryer_thread = threading.Thread(target=dryer, args=(dish_queue,)) 
    dryer_thread.start() 

dishes = ['salad', 'bread', 'entree', 'desert'] 
washer(dishes, dish_queue) 
dish_queue.join() 

從我的隊列模塊文檔,dish_queue.join()將阻塞主線程,直到未完成的任務計數(這裏未乾燥的菜)回到0的理解。但我不知道2 dryer_thread發生了什麼。

我發現,如果我在主程序中的空dish_queue上運行函數dryer,程序會卡住(順便說一下,這是從dish_queue.get()?)所謂的塊)。因此,如果dish_queue.join()解鎖主線程,那麼2 dryer_thread是否也會解鎖並釋放內存?什麼意味着無論如何在隊列文件?

回答

1

你的主要問題的簡短答案是什麼。

對於較長的答案,這裏有兩個並行的圖形,一個沒有等待: enter image description here

而一個具有: enter image description here

正如你可以看到,在一開始兩個兩個機線程在一個鎖,正如你正確理解的那樣,它是get()的區塊。現在,在第一種情況下,完成清洗器功能後主線程完成。當添加dish_queue.join()時,主線程等待dish_queue結束所有任務。所以當你說join()解鎖主線程時,這意味着它會刪除它自己的塊。正如你可以注意到的那樣,其他線程完全不受它影響並保持阻塞狀態。

至於什麼是塊,它是什麼時候線程或進程等待來自線程外部的輸入,或者在這種情況下,是否等待隊列中的元素。如果你想停止其他線程,你需要添加一個超時到get()(這將拋出一個異常並殺死線程),或者在dish_queue.join()之後終止它們。

+0

除了設置超時值之外,您還有什麼建議終止其他線程?我不確定是否將其他線程設置爲守護進程。另外,如果我不改變我的代碼,只是讓他們阻止,他們真的消耗我的記憶? – Nicholas

+0

順便說一句,你使用什麼併發監視器?這很優雅! – Nicholas

+0

通常情況下,帶有塊的線程與睡眠線程相同。它不會釋放它的內存,但也不會消耗任何額外的資源,所以基本上取決於你將來是否需要該線程。需要注意的是,只要主線程處於活動狀態,線程就會在那裏,因此您不應該打開新線程,而是將新元素添加到現有隊列中。 我使用pyCharm,這是一個很棒的IDE。 – Aruj

相關問題