2009-04-30 17 views
9

私はスレッドをself.outputに追加し、self.doneがTrue(または最大実行時間に達する)までループを実行します。Pythonスレッドとwhileループwhile

whileループを使用する以外にもこれを行うより効率的な方法は、実行されているかどうかを常にチェックします。 whileループは、CPUを放棄するwhileループの各反復の後に簡単な一時停止を作成するために

time.clock() 
while True: 

    if len(self.output): 
     yield self.output.pop(0) 

    elif self.done or 15 < time.clock(): 
     if 15 < time.clock(): 
      yield "Maximum Execution Time Exceeded %s seconds" % time.clock() 
     break 

答えて

11

あなたのスレッドはここでself.outputに追加されていますが、主なタスクはそれらを消費していますか?もしそうなら、これはQueue.Queueのために作られた仕事です。あなたのプロデューサーのスレッドがqueue.put(item)

[編集]でキューにアイテムを追加

import Queue 

# Initialise queue as: 
queue = Queue.Queue() 
Finished = object() # Unique marker the producer will put in the queue when finished 

# Consumer: 
try: 
    while True: 
     next_item = self.queue.get(timeout=15) 
     if next_item is Finished: break 
     yield next_item 

except Queue.Empty: 
    print "Timeout exceeded" 

self.done(例えば、複数の項目をチェックするときに、元のコードがレースの問題があります:何かのようにあなたのコードはなるはずフラグが設定される前にキューに追加され、最初のコードでコードが破棄される可能性があります)。 ΤΖΩΤΖΙΟΥの提案で更新されました。プロデューサスレッドは、代わりにキューに特別なトークン(Finished)を追加して、完了したことを示す必要があります。

注:複数のプロデューサスレッドがある場合は、すべて完了したタイミングを検出するためのより一般的なアプローチが必要です。同じ戦略でこれを達成することができます。各スレッドはFinishedマーカーになり、num_threadsマーカーが表示されると消費者は終了します。

+0

OoOooo、今話しています。 :D – Ian

+0

Queue.get()上でスレッドをブロックするように指示する方法はありますか?プロデューサがスレッドに何かを入れてタイムアウトしないようにして、正常に終了するようにしますか? – millimoose

+0

@Sii:スレッドデーモニックを作成するときにデーモンにマークすることができます。これは、プログラムが終了するとスレッドが終了することを意味します。 –

0

...それが実行している間、CPUが100%に急上昇する原因となる使用time.sleep(秒)。あなたが完了した後すぐに仕事を捕まえることの重要性に基づいて、各反復中に眠る時間を設定する必要があります。

例:

time.clock() 
while True: 

    if len(self.output): 
     yield self.output.pop(0) 

    elif self.done or 15 < time.clock(): 
     if 15 < time.clock(): 
      yield "Maximum Execution Time Exceeded %s seconds" % time.clock() 
      break 

    time.sleep(0.01) # sleep for 10 milliseconds 
+0

通常、スリープするとパフォーマンスが低下します。スリープを使用する前に同期を考慮する必要があります。 – Francis

0

あなたがここに同期プリミティブを使用する必要があります。ここを見てください:http://docs.python.org/library/threading.html

イベントオブジェクトは非常に単純なようで、問題を解決するはずです。また、条件オブジェクトまたはセマフォを使用することもできます。

私はEventオブジェクトを使用したことが一度もないので、例を投稿していません。代替案はおそらく単純ではありません。


編集:私はあなたの問題を理解し、本当にわかりません。ある条件が満たされるまでスレッドが待機できる場合は、同期を使用します。そうしないと誰かが投稿したsleep()ソリューションがCPU時間を浪費することになります。

0

使用ミューテックスモジュールまたはイベント/セマフォ

1

セマフォを使用します。作業スレッドが終了したら解放して、作業者がセマフォを終了するまで追加スレッドをブロックします。

ie。作業の開始時にself.done = threading.Semaphore()のようなものを行い、作業が完了したらself.done.release()のようにしてください。上記のコードでは、ビジーループではなく、単にself.done.acquire()を実行してください。ワーカースレッドが終了すると、制御が戻ります。

編集:私はあなたの必要なタイムアウト値に対処していないのでしょうか?このissueは、標準ライブラリでのセマフォータイムアウトの必要性について説明しています。