Python-スレッド化とWhile Trueループ
-
03-07-2019 - |
質問
self.outputに行を追加するスレッドと、self.doneがTrue(または最大実行時間に達する)まで実行するループがあります。
これを行うより効率的な方法はありますか? whileループにより、実行中にCPUが100%に急上昇します。
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
解決
ここで、スレッドはself.outputに追加され、メインタスクがそれらを消費しますか?その場合、これは Queue.Queue に合わせたジョブです。コードは次のようになります。
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"
プロデューサースレッドは、 queue.put(item)
[編集] self.doneの確認時に元のコードに競合の問題があります(たとえば、フラグが設定される前に複数のアイテムがキューに追加され、コードが最初の1つ)。 &#932;&#918;&#937;&#932;&#918;&#921;&#927;&#933;からの提案で更新-プロデューサースレッドは、代わりに特別なトークン(Finished)をキューに追加して、完了したことを示します。
注:複数のプロデューサースレッドがある場合、それらがすべて終了したことを検出するためのより一般的なアプローチが必要になります。同じ戦略でこれを達成できます-各スレッドはFinishedマーカーであり、コンシューマはnum_threadsマーカーを検出すると終了します。
他のヒント
セマフォを使用します。作業スレッドが終了したら解放し、ワーカーがセマフォで終了するまで追加スレッドをブロックします。
ie。ワーカーで、作業の開始時に self.done = threading.Semaphore()
のように、終了したら self.done.release()
のようにします。上記のコードでは、ビジーループの代わりに、単に self.done.acquire()
を実行します。ワーカースレッドが終了すると、制御が戻ります。
編集:必要なタイムアウト値に対処していないのではないかと心配しています。この問題では、標準ライブラリでのセマフォタイムアウトの必要性について説明しています。
time.sleep(seconds)を使用して、whileループの各反復後に短い一時停止を作成し、CPUを放棄します。ジョブが完了した後すぐにキャッチすることがどれだけ重要かに基づいて、各反復中にスリープする時間を設定する必要があります。
例:
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
mutexモジュールまたはイベント/セマフォを使用
ここで同期プリミティブを使用する必要があります。こちらをご覧ください: http://docs.python.org/library/threading.html 。
イベントオブジェクトは非常に単純に見えるため、問題を解決するはずです。条件オブジェクトまたはセマフォを使用することもできます。
Eventオブジェクトを使用したことがないため、例を投稿しません。代替案はおそらくそれほど単純ではありません。
編集:あなたの問題を理解したかどうかは確かではありません。スレッドが何らかの条件が満たされるまで待機できる場合は、同期を使用します。それ以外の場合、誰かが投稿した sleep()
ソリューションは、CPU時間がかかりすぎます。