我从我的主类执行多个任务:
ExecutorService executor = Executors.newFixedThreadPool(N);
for (int i = 0; i < M; i++) {
executor.execute(task);
}
executor .shutdown();
while (!executor.isTerminated()){} //block
任务是implements Runnable
。
在run()
方法中,我调用了一些带有检查异常的api,这意味着我需要使用try-catch块来包围调用。
所以,我的主类没有办法知道抛出了异常。
我该如何解决这个问题?
答案 0 :(得分:3)
您可以改为使用Callable:
Callable<?> task = new Callable<Void> () {
public Void call() throws Exception {
someCodeThatThrowsCheckedExceptions();
return null;
}
}
然后:
Future<?> f = executor.submit(task);
try {
f.get();
} catch (ExecutionException e) {
System.out.println("task threw exception: " + e.getCause().getMessage());
}
答案 1 :(得分:0)
始终重新抛出允许调用者知道的异常,否则异常可能会逃脱。你可以在Java Concurrency in Practice一书中找到很好的解释。对不起,我应该把它作为评论给你,但我的分数不允许我:)
答案 2 :(得分:0)
您可以在主要例外中创建UncheckedException。假设您已经创建了自己的UncheckedException
类,扩展了RuntimeException
,定义了所有必需的构造函数。你可以说,
@Override
public void run() {
try {
//some code that throws checked exception
}
catch(Exception e) {
throw new UncheckedException(e);
}
}
此代码将编译,因为此处不需要throws
声明
答案 3 :(得分:0)
如果您可以修改任务以实现Callable
,则可以从call()中抛出已检查的异常
由于您的任务未返回值,请使用Callable<Void>
class Task implements Callable<Void> {
public Void call throws YourAPIException {
//code that throws a checked exception
return null;
}
}
Callable<?>
与Runnable
的不同之处在于它可以抛出已检查的异常并返回结果
call()
的方法签名允许您抛出已检查的异常
V call() throws Exception
答案 4 :(得分:0)
根据我的说法,这个好看的解决方案是实施Callable<V>
而不是Runnable
。两个主要区别是Callable
可以抛出已检查的异常,并且它可能返回一个值。您可以通过实施Callable<Void>
来克服返回值。
您需要做什么:
Callable<Void>
而不是Runnable
- 将void run()
更改为Void call() throws Exception
。无需尝试/捕获已检查的异常。添加return null;
语句。 Future<Void> checkableResult = ExecutorService.submit(Callable<Void>)
checkableResult.get()
来检查是否引发了异常,如果有get()
,则会引发ExecutionException
。 getCause()
可以检索原始异常。特别注意Callable.isDone()
是阻塞的 - 所以定期检查Runnable
可能就是你想要的(否则你也可以在同一个线程中运行它)。另一种选择是在volatile boolean isDone
(volatile Exception exception
和{{1}})中构建功能 - 但为什么要重新发明轮子?