2011-04-03 9 views
0

私は空き時間に画像ボードスクレーパーを書いて、スレッドに関することを教えています。現在、私はこの作業を容易にするためにプロデューサ/コンシューマタイプのパターンを使用しています。しかし、私は問題に遭遇しています。異なるスレッド上のオブジェクトのインスタンスの追跡ステータス?

現在、スレッドセーフなキューの特定の種類を監視して処理する「キュープロセッサ」があります。これらのキュープロセッサは、X秒ごとに対象キューをポーリングし、キューに処理待ちのアイテムがある場合、キュープロセッサはそのアイテムをデキューし、そのアイテムで新しいスレッドをスピンアップしてスレッドを開始します。各スレッドでは、長時間実行されるメソッドが呼び出されます(Webサイトへの接続やファイルのダウンロードなど)。このようにして、各アイテムは独自のスレッドを取得して実行されます。

各スレッドで処理されている各アイテムのステータスを報告する方法がわかりません。

たとえば、メインスレッドMTがあるとします。 MTは、子スレッドT1、T2、T3、T4、およびT5を生成します。各スレッドには、対応するオブジェクトO1 ... O5があります。これらのオブジェクトは、そのスレッド上で処理されている間に、例えば、S1、S2、S3-の3つの異なる状態にあり得る。

オブジェクトOのステータスが変更されたときに、各オブジェクトOのステータスをメインスレッドMTに報告するにはどうすればよいですか?

ステータスを報告するためにイベントを使用しようとしましたが、その周りにうっかりした結果が発生しています。私はスレッドとイベントの使い方について少し調べましたが、それほど遠くには達しませんでした。

ご協力いただければ幸いです。

ありがとうございます。

答えて

1

ステータス更新を報告するために使用される別のスレッドセーフなキューを作成する方法もあります。スレッドがステータスを変更するたびに、ジョブの一意の識別子、新しいステータス、スレッドID、その他必要と思われるものを含むタプル/オブジェクトがプッシュされます。

もう一度やり直すと、誰がキューをポーリングするのでしょうか?あなたはジョブキューのチェックの間にあなたのメインスレッドでそれを行うことができますが、それは醜いかもしれませんし、不必要に処理を遅くする可能性があります。これを行うための別のスレッドを生成することもできますが、これは役立たないようにステータスをメインスレッドに報告する必要があると思います。

実際にプログラムを構成するには、より良い方法があります。メインスレッドがジョブキューを連続的にポーリングしてスレッドを作成するのではなく(代わりにかなり高価です)、代わりにスレッドプールを作成してジョブスレッドにポーリングを実行させることができます。これにより、メインスレッドは、それが探しているイベントを待っているステータスキューをポーリングできるようになります。ここで

は、概念を説明するためにいくつかの擬似コードです:

基本的に
main_thread() 
    ... 
    thread_pool = create_pool(get_core_count()); 
    thread_pool.execute(worker_thread); 

    while(true) 
     status = status_queue.pop_blocking(); 
     if (check_status(status) == WE_BE_DONE) 
      break; 

    thread_pool.interrupt(); 
    ... 

worker_thread() 
    while(true) 
     job = job_queue.pop_blocking(); 
     process_job(job); 
     status_queue.push({job.id, thread_id, WE_DONE}); 

、何これが行うことは、あなたが持っているCPUコアごとに1つのワーカースレッド(で始まるには、[OK]デフォルト)を含んスレッドプールを作成することです。次に、各ワーカースレッドで関数worker_threadを実行します(関数は自明です)。次に、メインスレッドは、ステータスキューに特定されていないイベントがないかどうかを継続的にチェックします。これが発生すると、ワーカースレッドが強制終了され、残りのプログラムの実行が再開されます。

この例では注意すべき点が3つあります。まず、手動のポーリング実装では、ブロックポップコール(この例ではpop_blocking)を使用することをお勧めします。使用するのがずっと簡単で、おそらくはるかに効率的です。次に、thread_pool.interrupt()を使用してジョブスレッドを強制終了しましたが、使用している言語やライブラリに応じて実行するのが最もスマートな方法ではないかもしれません。あなたの言語がそのようなことをサポートしている場合は、do_job(job)コールをtry catchステートメントで囲むことをお勧めします。

あなたの質問は詳細(言語は1つに使用されています)には非常に軽いので、あなたが達成しようとしているものにソリューションを適応させる必要があることに注意してください。これはまだあなたに良い出発点を与えるはずです。

関連する問題