如何将超时从一个FutureTask传播到另一个由其Callable使用的依赖?

时间:2014-01-21 10:57:30

标签: java multithreading asynchronous futuretask

我处于以下情况(也许我已经过度设计了整个事情,或者我处于完全僵局,但不能想到另一种方式):

  • 取一个或多个实现异步计算的FutureTask(通过网络监听组播数据包来传递不同类型的统计数据),我们将其命名为MulticastStatisticsProvider
  • 采取另一个依赖于第一个任务的计算来执行额外的计算(将公式与公式结合以暴露一些合成信息),这个计算也是异步的,所以在另一个FutureTask中定义我们称之为{{1 }},
  • 问题:我们希望FormulaComputing在调用FormulaComputing.get(timeout, timeUnit)时将超时传播到其内部Callable,但无法找到实现此目的的方法。

下面,我到目前为止所实现的代码状态:

  • 这是来电者代码。

    MulticastStatisticsProvider.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改变内省来改变FutureTask的私人内部Callable字段,但内省和反思是通常是可以避免的黑客攻击。

1 个答案:

答案 0 :(得分:2)

如果您使用Guava,对于ListenableFuture来说,这似乎是个好例子:

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);

您可以ListenableFutureFutureTask提交给ListeningExecutorService,或者使用ListenableFutureTask来提取{{1}}。