2013-03-02 14 views
12

私はPythonのスレッドと例をキュー

http://docs.python.org/2/library/queue.html)のpythonに新しい(私はPHPから来た)、私はチュートリアルを読み、数日間のことをしようが、私はこのキューの例を理解することはできませんしてきましたよ
def worker(): 
    while True: 
     item = q.get() 
     do_work(item) 
     q.task_done() 

q = Queue() 
for i in range(num_worker_threads): 
    t = Thread(target=worker) 
    t.daemon = True 
    t.start() 

for item in source(): 
    q.put(item) 

q.join()  # block until all tasks are done 

私は分かりませんが、ワーカースレッドが完了して存在する方法です。アイテムが利用可能になるまでq.get()ブロックを読んだので、すべてのアイテムが処理され、キューに何も残らない場合、q.get()が永遠にブロックされないのはなぜですか?

答えて

9

スレッドはこのコードで正常に終了しません(キューが空の場合は実際にブロックされます)。彼らはdaemon threadsであるので、プログラムはそれらを待つことはありません。

プログラムはすぐに終了せず、q.joinq.task_done呼び出しのために永久にブロックされません。

未完了タスクの数は、アイテムがキューに追加されるたびに増加します。コンシューマスレッドがtask_done()を呼び出すと、アイテムが取得され、そのすべての作業が完了したことを示すたびにカウントがダウンします。未完了タスクの数がゼロになると、join()はブロック解除され、デーモンスレッドを待つことなくプログラムが存在します。

-3

私は同じ問題がありました。すべてのスレッドが完了すると、プロセスリストに "sleeping threads"が表示されました(で、<pid>のプロセスIDはps aux | grep pythonです)。

「無限ループ」while Truewhile not q.empty():に置き換えてこの問題を解決しました。

「スリープスレッド」の問題を修正しました。

def worker(): 
    while not q.empty(): 
     item = q.get() 
     do_work(item) 
     q.task_done() 

q = Queue() 
for i in range(num_worker_threads): 
    t = Thread(target=worker) 
    t.daemon = True 
    t.start() 

for item in source(): 
    q.put(item) 

q.join()  # block until all tasks are done 
+0

このソリューションはかなり危険です。ワーカースレッドが速い場合、キューに項目が追加される前に 'q.empty()'をテストしてから、何もしないうちに終了します。同様に、キューに1つのアイテムが残っていて、2つのスレッドが 'q.empty()'を同時にテストすると、それらは両方とも続行しますが、1つはアイテムをキューから取得し、もう1つは 'q.get() '。 –

関連する問題