1

私は次のような状況です (おそらく、すべてをオーバーエンジニアリングしたか、完全に行き詰まりましたが、それを行う別の方法を考えることができません):

  • FutureTask非同期計算 (さまざまな種類の統計情報を伝達するマルチキャスト パケットをネットワークでリッスンすること) を実現する1 つまたは複数を取り、名前を付けますMulticastStatisticsProvider
  • FutureTaskこの最初のタスクに依存する別の計算を行って、追加の計算を実行します (統計と数式を組み合わせて、いくつかの合成情報を公開します)。この計算も非同期であるため、別のFormulaComputing.
  • 問題:呼び出し時にFormulaComputing.get(timeout, timeUnit)タイムアウトを内部に伝播させたいのですが、これを達成する方法が見つかりません。CallableMulticastStatisticsProvider.get(timeout, timeUnit)

以下、これまでに達成したコードの状態:

  • これが発信者コードです。

    // This is the code creating the formula computing code.
    public FormulaComputing getFormulaComputing() {
      // Retrieve from another service a list of FutureTasks already
      // scheduled for execution in their own ThreadPool.
      List<MulticastStatisticsProvider> requiredTasks = service.getRequiredTasks();
      // Create the formulaComputing task and schedule it for execution
      FormulaComputing formulaComputing = new FormulaComputing(requiredTasks);
      threadPool.execute(formulaComputing);
      return formulaComputing;
    }
    
    // And then, from another caller
    getFormulaComputing().get(10, TimeUnit.SECONDS);
    
  • これはFormulaComputingコードです:

    public class FormulaComputing extends FutureTask<Object> {
      private long timeout;
      private TimeUnit timeUnit;
      private Map<String, Future<Map<String, ? extends AbstractSymposiumMessage>>> promises;
      private Closure<Object> callback;
    
      public FormulaComputing(List<MulticastStatisticsProvider> dependentTasks, Closure<Object> callback) {
        super(new Callable<Object>() {
          @Override
          public Object call() throws Exception {
            List<Object> results = new ArrayList<Object>();
            for (MulticastStatisticsProvider task : dependentTasks) {
              // Here is the problem, you cannot access field values in constructor: "Cannot refer to an instance method while explicitly invoking a constructor".
              results.add(task.get(getTimeout(), getTimeUnit()));
            }
            return callback.call(results.toArray());
          }
        });
      }
    
      @Override
      public Object get(long timeout, TimeUnit timeUnit) throws InterruptedException, ExecutionException, TimeoutException {
        this.timeout = timeout;
        this.timeUnit = timeUnit;
        return super.get(timeout, timeUnit);
      }
    }
    

私は自分のカスタムメソッドで手作りの私的な内部syncフィールドを変更するためにイントロスペクションを通過することを想像しましたが、イントロスペクションとリフレクションは一般的に回避可能なハックです.FutureTaskCallableget

4

1 に答える 1

3

Guavaを使用する場合、 ListenableFutures の適切なケースのように見えます。

List<ListenableFuture<Object>> requiredTasks = ...;

ListenableFuture<List<Object>> requiredTasksResult = Futures.allAsList(requiredTasks);

ListenableFuture<Object> resultFuture = Futures.transform(requiredTasksResult, new Function<List<Object>, Object>() {
    public Object apply(List<Object> results) {
        // Apply computing formula
    }
}, threadPool); // Function will be executed in threadPool

Object result = resultFuture.get(10, TimeUnit.SECONDS);

に送信するか、代わりに使用することListenableFutureで取得できます。FutureTaskListeningExecutorServiceListenableFutureTask

于 2014-01-21T11:16:56.793 に答える