2016-08-02 101 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

相关问题