【发布时间】:2011-01-18 11:12:57
【问题描述】:
我正在使用 java.util.concurrency 框架实现一些代码。我会将一组可调用对象传递给一个类,该类将并行执行它们。我正在尝试找出以类型安全的方式获取每个响应的最佳方法。这里有一些代码可以帮助解释我在做什么:
首先我创建我的Callables,它们是要并行调用的工作单元。例如,这里第一个工作单元返回一个String,第二个工作单元返回一个Integer:
Callable<String> firstCallable = new Callable<String>(){
public String call() {...}
};
Callable<Integer> secondCallable = new Callable<Integer>(){
public Integer call() {...}
};
现在我将它们触发到我的框架中以并行运行它们,诀窍是获取适当响应对象的句柄。这是一个有效的实现:
Map<Callable,Object> responseMap = ParallelSender.send(firstCallable,
secondCallable);
其中Object 是特定Callable 的响应。因此,您可以这样做:
String firstCallableResponse = (String)responseMap.get(firstCallable);
Integer secondCallableResponse = (Integer)responseMap.get(secondCallable);
所以我的问题是,从地图获取时是否可以避免强制转换?这不会编译,但我正在考虑这些方面:
Map<Callable<T>, T> responseMap = ParallelSender.send(...);
String firstCallableResponse = responseMap.get(firstCallable);
这样返回的值基于Callable 键的类型参数。我担心的是,如果有人重构工作单元的返回类型(比如从Integer 到BigDecimal 或其他),那么来自Object 的转换将永远不会被自动重构工具捕获,并可能导致运行时问题。
结论:感谢所有有用的 cmets 和下面的讨论,我采取了稍微不同的策略(尽管我认为 Sean Patrick Floyd 对我上面的问题的正确性)。我最终将响应映射全部删除并使用响应填充 Callable 对象。以下是相关代码sn-ps:
public abstract class AbstractParallelCallable<V> implements Callable<V> {
/** The response generated by the Call method of this class. */
private V callableResponse;
public V getResponse() {
return callableResponse;
}
public void setResponse(V response) {
callableResponse = response;
}
}
因此,我有一个抽象实现,它通过存储响应来包装 Callable 对象。接下来,在我的并行处理中,我得到每个 Future 创建的响应并填充 AbstractParallelCallable:
for (ParallelFutureTask<Object> future : futures) {
try {
future.getCallableHandle().setResponse(future.get());
} catch(Exception e) {...}
}
其中 getCallableHandle 通过提供对 Callable 对象的引用返回 AbstractParallelCallable 对象和 ParallelFutureTask 包装器 FutureTask。执行后,调用代码可以这样做:
Integer theResult = firstCallable.getResponse();
【问题讨论】: