多线程python程序永远不会退出

时间:2016-06-19 14:07:40

标签: multithreading python-3.x python-multiprocessing

我尝试使用python 3.4.3解释器在多线程python程序下运行。 我的期望是,在获取并处理了dish_queue中的所有项目之后(这是函数task_done的目的,对吗?),dish_queue将不再阻止程序,因此程序可以正常退出。

结果是在打印出行Drying desert <Thread(Thread-2, started 140245865154304)>之后,无论行dish_queue.join()是否被评论,程序都不会退出。 似乎主线程卡在washer(dishes,dish_queue)语句中?任何人都可以向我解释原因吗?

$ cat threading_dish.py     
import threading,queue
import time

def washer(dishes,dishqueue):
  for dish in dishes:
    time.sleep(5)
    print("washing",dish,threading.current_thread())
    time.sleep(5)
    dishqueue.put(dish)


def dryer(dishqueue):
  while True:
    dish=dishqueue.get()
    print("Drying",dish,threading.current_thread())
    #time.sleep(10)
    dishqueue.task_done()

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()

$ python3 threading_dish.py
washing salad <_MainThread(MainThread, started 140245895784256)>
Drying salad <Thread(Thread-1, started 140245873547008)>
washing bread <_MainThread(MainThread, started 140245895784256)>
Drying bread <Thread(Thread-2, started 140245865154304)>
washing entree <_MainThread(MainThread, started 140245895784256)>
Drying entree <Thread(Thread-1, started 140245873547008)>
washing desert <_MainThread(MainThread, started 140245895784256)>
Drying desert <Thread(Thread-2, started 140245865154304)>

相比之下,如果我运行程序的多处理对应程序,程序可以在最后一次打印输出后正常退出。 多线程和多处理之间是否存在导致相反运行结果的差异?

$ cat multiprocessing_dishes.py 
import multiprocessing as mp
import time
def washer(dishes,output):
  for dish in dishes:
    print('washing', dish, 'dish',mp.current_process())
    output.put(dish)

def dryer(input):
  while True:
    dish=input.get()
    print('Drying',dish,'dish',mp.current_process())
    time.sleep(5) 
    input.task_done()

dishqueue=mp.JoinableQueue()

dryerproc=mp.Process(target=dryer,args=(dishqueue,))
dryerproc.daemon=True
dryerproc.start()

dishes=['xxx','asa','aass']
washer(dishes,dishqueue)


dishqueue.join()

$ python3 multiprocessing_dishes.py 
washing xxx dish <_MainProcess(MainProcess, started)>
washing asa dish <_MainProcess(MainProcess, started)>
washing aass dish <_MainProcess(MainProcess, started)>
Drying xxx dish <Process(Process-1, started daemon)>
Drying asa dish <Process(Process-1, started daemon)>
Drying aass dish <Process(Process-1, started daemon)>
$

1 个答案:

答案 0 :(得分:0)

https://docs.python.org/3.4/library/queue.html

Queue.get()阻塞,因此在不再生成队列之后,干燥器线程将无限期地阻塞。 您需要以某种方式向干燥器螺纹发出洗涤过程已完成的信号。

您可以通过在while循环条件中查询共享变量来实现此目的,或者通过为每个线程排列毒丸来实现此目的。毒丸是预先确定的值,它允许消费线程知道它需要终止。