如果我想并行执行资源密集型代码, AFAIK 提交Callable
/Runnable
到ExecutorService
是要走的路。因此我的方法结构:
public class ServiceClass {
protected final ExecutorService executorService = Executors.newCachedThreadPool();
public Future<Result> getResult(Object params) {
if (params == null) {
return null; // In situations like this the method should fail
}
// Do other fast pre-processing stuff
return executorService.submit(new CallProcessResult(params));
}
private class CallProcessResult implements Callable<Result> {
private Object params;
public CallProcessResult(Object params) {
this.params = params;
}
@Override
public Result call() throws Exception {
// Compute result for given params
// Failure may happen here too!
return result;
}
}
}
public class Result {
...
}
我在上面的代码中标记了两个可能发生故障的位置。对于这两种情况,可用于错误处理的选项完全不同。
在提交任务之前,可能会出现参数无效、一些可能会失败的快速预处理代码等问题。
我在这里看到了几种表示失败的方法:
- 如果
params
提供无效,则getResult
立即返回 null。在这种情况下,我getResult
每次调用它时都必须检查是否返回 null。 - 抛出已检查的异常而不是上述异常。
- 实例化根据请求
Future<Result>
返回 null 的a。get()
我会用 Apache Commons 做到这一点ConcurrentUtils.constantFuture(null)
。在这种情况下,我希望getResult
总是返回一些 non-nullFuture<Result>
。我更喜欢这个选项,因为它与第二种情况一致。
在任务执行期间,我可能会遇到严重的错误,例如内存不足、文件损坏、文件不可用等。
- 我想在我的情况下更好的选择是返回 null,因为任务的结果是一个对象。
- 此外,我可以抛出检查异常并处理它们
ThreadPoolExecutor.afterExecute
(如 NiranjanBhat 所建议的那样)。请参阅处理来自 Java ExecutorService 任务的异常
哪种做法更好(在这两种情况下)?
也许有不同的方法可以做到这一点,或者我应该使用一种设计模式?