10

現在のコードでは、最終的に結果が得られる一連の非同期プロセスを使用しています。結果を戻り値とする同期メソッドによってそれぞれがアクセスされるように、これらのそれぞれをラップする必要があります。これらの多くを同時に実行できるように、エグゼキュータ サービスを使用してこれを実行したいと考えています。Future が私の実装に関連している可能性があると感じていますが、これを実現するための良い方法がわかりません。

私が今持っているもの:

public class DoAJob {
  ResultObject result;

  public void stepOne() {
    // Passes self in for a callback
    otherComponent.doStepOne(this);
  }

  // Called back by otherComponent once it has completed doStepOne
  public void stepTwo(IntermediateData d) {
    otherComponent.doStepTwo(this, d);
  }

  // Called back by otherComponent once it has completed doStepTwo
  public void stepThree(ResultObject resultFromOtherComponent) {
    result = resultFromOtherComponent;
  //Done with process
  }
}

これは内部的にはかなりうまく機能しましたが、次のような戻り値を持つ同期メソッドにプロセスをマップする必要があります。

public ResultObject getResult(){
  // ??? What goes here ???
}

これをエレガントに実装する方法について誰かが良い考えを持っていますか?

4

5 に答える 5

9

非同期操作 (完了時にコールバックを実行する) を同期/ブロッキング操作に変更する場合は、ブロッキング キューを使用できます。必要に応じて、これを Future オブジェクトにまとめることができます。

  1. 要素を 1 つだけ保持できるブロッキング キューを定義します。

    BlockingQueue<Result> blockingQueue = new ArrayBlockingQueue<Result>(1);

  2. 非同期プロセスを開始し (バックグラウンドで実行されます)、完了時に結果をブロッキング キューに追加するようにコールバックを記述します。

  3. フォアグラウンド/アプリケーション スレッドで、要素が使用可能になるまでブロックするキューから take() を実行します。

    Result result = blockingQueue.take();

Future のようなものを使用して、以前に似たようなことを書きました (フォアグラウンド スレッドは、リモート マシンからの非同期応答のためにブロックする必要があります)。ここでサンプル コードを見つけることができます。

于 2013-04-04T16:23:22.877 に答える
1

Guava ライブラリで同様のことを行いました。これらのリンクは、正しい方向を示している可能性があります。

Guava を使用して非同期呼び出しをチェーンすることは可能ですか?

https://code.google.com/p/guava-libraries/wiki/ListenableFutureExplained

于 2013-04-04T16:00:14.040 に答える
0

手を汚したい場合は、これを行うことができます

ResultObject result;

public void stepOne() 

    otherComponent.doStepOne(this);

    synchronized(this)
        while(result==null) this.wait();
    return result;

public void stepThree(ResultObject resultFromOtherComponent) 

    result = resultFromOtherComponent;

    synchronized(this)
        this.notify();

または、BlockingQueue、Semaphore、CountdownLatch、Phaser などの高レベルの同時実行ツールを使用できます。

これはスレッド セーフではないことに注意してください。2 つのスレッドが同時にDoAJob呼び出された場合に問題が発生します。stepOne

于 2013-04-04T16:30:19.483 に答える
0

invokeAll(..)を使用することをお勧めします。一連のタスクをエグゼキューターに送信し、最後のタスクが完了するまでブロックします (成功/例外あり)。次に、完成した Future オブジェクトのリストを返すので、それらをループして、結果を単一の ResultObject にマージできます。

単一のタスクのみを同期的に実行する場合は、次を使用できます。

executor.invokeAll(Collections.singleton(task)); 

- 編集 -

今、私はあなたのニーズをよりよく理解していると思います. 独立した一連のタスクを送信する方法が必要だと思います。この回答に投稿したコードを見てください。

于 2013-04-04T16:09:19.353 に答える