0

何らかの計算を行う n 個のワーカーがあると仮定しましょう。計算にはしばらく時間がかかる場合があり、n 回の計算が並行して実行される場合があります。各ワーカーは、作業を行うために何らかのデータ構造 (ワーカー間で共有されない) を必要とします。

マスターの初期化中に各ワーカーをセットアップし、必要なデータ構造をワーカーのコンストラクターに渡すことを考えました。

public class Master {

  public Master() {
     // initialize n Workers and "register" them "somewhere"
  }

  public boolean doCompute(int someInput) throws NoIdleWorkerException {
     // check if there is an idle Worker, otherwise throw NoIdleWorkerException
     // call the idle Worker, hand over someInput and wait for the result
     // synchronously return the result
  } 
}

Worker は Runnable を実装してから Thread に引き渡すことができます。Worker のインスタンスは再利用できます。

public class Worker implements Runnable {

  private SomeDataStructure ds;

  public Worker(SomeDataStructure ds) {
     this.ds = ds;
  }

  public void run() {
     // may call doCompute, but run() doesn't has a return type
  }

  public boolean doCompute(int someInput) {
     // do the computation an return
  } 
}

Worker インスタンスを管理する最良の方法は何ですか? Worker インスタンスがアイドル状態の場合にのみ Thread を返し、それ以外の場合は null を返す ThreadFactory を使用することを考えていました。このアプローチを使用すると、一部のデータ構造で Worker インスタンスを管理する必要があります。

また、Master.doCompute(int someInput) には戻り値がありますが、その計算は Thread によって行われるため、非同期的に、Futures を使用する必要がある場合があります。代替手段はありますか?

4

1 に答える 1

1

マスターが特定の呼び出しに対してすべてのワーカーの結果を処理する必要があると仮定すると、各ワーカーを Callable として実装し、実行する作業を呼び出し関数に実装します。

次に、マスターは、渡されたものから Callables のリストを生成し、invokeAll メソッドを介して ThreadPoolExecutor に渡します (つまり、この種の並列処理に実際に使用されているスレッドの数を制御できます)。

invokeAll は、Future のリストを返します。Future は、完了したか、タイムアウトの期限が切れています (設定することを選択した場合)。キャンセル(タイムアウト)したかどうかを確認できます。

詳細については、 http://docs.oracle.com/javase/7/docs/api/java/util/concurrent/AbstractExecutorService.html#invokeAll(java.util.Collection)を参照してください。

于 2013-08-12T14:07:52.667 に答える