我从主类执行多个任务:
ExecutorService executor = Executors.newFixedThreadPool(N);
for (int i = 0; i < M; i++) {
executor.execute(task);
}
executor .shutdown();
while (!executor.isTerminated()){} //block
task是一个 implements Runnable
.
在 run()
方法,我调用了一些带有选中异常的api,这意味着我需要用try-catch块包围调用。
所以,我的主类不可能知道抛出了异常。
我怎样才能解决这个问题?
5条答案
按热度按时间rn0zuynd1#
如果你能修改你的任务来实现
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()
允许您抛出选中的异常5cnsuln72#
在我看来,解决问题的好办法是实施
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()
,它抛出一个ExecutionException
如果是的话。原始异常可以通过getCause()
. 请特别注意get()
是阻塞-所以定期检查Callable.isDone()
可能是您想要的(否则您最好在同一个线程中运行它)。另一个选择是将功能构建到
Runnable
(volatile boolean isDone
和一个volatile Exception exception
)-但为什么要重新发明轮子?fwzugrvs3#
总是重新抛出异常,让调用者知道它,否则异常可能只是转义。您可以在《实践中的java并发》一书中找到很好的解释。对不起,我应该把它作为你的评论,但我的分数不允许我:)
svdrlsy44#
可以从主异常中创建uncheckedexception。假设你已经创建了自己的
UncheckedException
扩展的类RuntimeException
,定义所有必需的构造函数。你可以说,这段代码将编译,因为不需要
throws
在此声明up9lanfz5#
您可以改用可调用的:
然后: