0

Javaでは、次の問題に対する効率的な解決策は何ですか:

複数のスレッド (10 ~ 20 程度) を生成するジョブ (「ジョブ クリエーター」) と、それらを実行できる単一のスレッド (「ワーカー」) があります。ジョブ作成者がジョブを投稿したら、ジョブが終了するのを待って、「完了」以外の結果が得られない状態で、ジョブを続行する必要があります。

ジョブをワーカー スレッドに送信するには、リング バッファまたは同様の標準的なファンイン セットアップがおそらく良い方法ではないでしょうか? しかし、ジョブクリエーターが自分の仕事が完了したことを知るかどうかは、私にはよくわかりません..

ジョブ作成者はスリープし、作業が完了するとワーカーが中断する可能性があります。または、各ジョブ作成者は、チェックしてワーカーが設定するアトミックブール値を持つことができます。どちらもあまりいい気分ではありません。可能な限り少ないロック (可能であればなし) でそれを行いたいと思います。明確にするために、私が探しているのはスピードであり、必ずしも単純さではありません。

誰か提案はありますか?同時実行戦略に関する読み物へのリンクも大歓迎です!

4

2 に答える 2

1

これを行うにはいくつかの方法があります。おそらく最速の方法はSemaphore、シングルスレッドのエグゼキューターを使用することです。

private final Executor executor = Executors.newSingleThreadExecutor();

public void submitJob() {
    Semaphore semaphore = new Semaphore(0);
    executor.execute(new Job(semaphore));
    semaphore.acquire(); // Will block until semaphore.release() below
}

次に Job クラスで:

public class Job implements Runnable {

    private final Semaphore semaphore;

    public Job(Semaphore semaphore) {
        this.semaphore = semaphore;
    }

    @Override
    public void run() {
        // Perform task and run the actual job
        semaphore.release(); // Cues the submitter to continue at semaphore.acquire()
    }
}

Semaphoreかなり高速で、synchronizedブロックを使用するよりもはるかに高速です。

編集:これにより、 からの多くのオーバーヘッドが回避されるFutureため、他の人が提案した実装よりもおそらく高速であるFutureことに注意する必要がありますが、自分でテストしないと確信が持てません。

于 2012-09-11T21:30:08.900 に答える
1

シングル スレッドのエグゼキュータ サービスを優先し、それにワーカー インスタンスを送信するだけです (結果の未来を取得します)。次に、結果が利用可能になるまでブロックして結果を取得する両方の未来を get() できます

public class TheWorker {
  private final ExecutorService service = Executors.newSingleThreadedExecutor();

  public Result work(Job job) {
    return service.submit(new Callable<Result>(){
      ...
    }).get()
  }

}
于 2012-09-11T21:14:29.593 に答える