我处于以下情况(也许我已经过度设计了整个事情,或者我处于完全僵局,但不能想到另一种方式):
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
字段,但内省和反思是通常是可以避免的黑客攻击。
答案 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);
您可以ListenableFuture
将FutureTask
提交给ListeningExecutorService
,或者使用ListenableFutureTask
来提取{{1}}。