2016-06-19 8 views
0

私は、マルチスレッドのPythonプログラムの下で、Python 3.4.3インタプリタを使って実行しようとしました。 私は、dish_queue内のすべてのアイテムが取得されて処理された後(つまり、これはtask_done関数の目的です)、dish_queueはプログラムをそれ以上ブロックしないので、プログラムは正常に終了できます。マルチスレッドのPythonプログラムは決して終了しません

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

答えて

0

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

Queue.get()ブロック、そのキューがもはやに生産された後、あなたのドライヤーのスレッドが無期限にブロックします。 ドライヤースレッドに何らかの方法で、洗浄プロセスが完了したことを通知する必要があります。

whileループの条件でシェア変数を照会するか、スレッドごとにポイズンピルをエンキューすることで、これを実現できます。ポイズンピルは、消費スレッドが終了する必要があることを知らせる事前に決められた値です。

+0

プログラムのマルチプロセッシングの対応部分を追加しましたが、JoinableQueue.get()はブロックしませんでした。なぜそのような違いがありますか? – Zii

+0

2番目の例では、ドライヤースレッドはデーモンスレッドです。デーモンスレッドは、終了を妨げないスレッドです。つまり、アプリケーションの実行可能スレッドおよびブロックされたスレッドがすべてデーモンスレッドである場合、アプリケーションは終了します。ドライバースレッド**はQueue.get()でブロックしますが、プロセスが終了するのを防ぐだけでなく、メインスレッドが実行を終了するとプロセスが終了します。メインスレッド(または別の非デーモンスレッド)にもっと多くの作業があった場合、デーモンスレッドはブロックされたままなので、これは一般的には悪い解決策であると私は言います。 –

関連する問題