0

私は自由な時間に画像掲示板スクレーパーを書いていて、主にスレッドについて教えてくれます。現在、私はこの取り組みを容易にするために生産者/消費者タイプのパターンを使用しています。しかし、私は問題にぶつかっています。

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

各スレッドで処理されている間、各アイテムのステータスを報告する方法を理解するのに苦労しています。

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

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

イベントを使用してステータスを報告しようとしましたが、その周りでいくつかの奇妙な結果に遭遇しています。スレッドとイベントの使用について少しググったが、それほど遠くはなかった。

どんな助けでもいただければ幸いです。

ありがとうございました。

4

1 に答える 1

1

これを行う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つに使用されている言語)についてはかなり軽いので、あなたが達成しようとしているものにソリューションを適応させる必要があることに注意してください。これはまだあなたに良い出発点を与えるはずです。

于 2011-04-03T08:16:12.343 に答える