从runnable中重试检查的异常

pcrecxhr  于 2021-06-30  发布在  Java
关注(0)|答案(5)|浏览(367)

我从主类执行多个任务:

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块包围调用。
所以,我的主类不可能知道抛出了异常。
我怎样才能解决这个问题?

rn0zuynd

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() 允许您抛出选中的异常

V call() throws Exception
5cnsuln7

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 )-但为什么要重新发明轮子?

fwzugrvs

fwzugrvs3#

总是重新抛出异常,让调用者知道它,否则异常可能只是转义。您可以在《实践中的java并发》一书中找到很好的解释。对不起,我应该把它作为你的评论,但我的分数不允许我:)

svdrlsy4

svdrlsy44#

可以从主异常中创建uncheckedexception。假设你已经创建了自己的 UncheckedException 扩展的类 RuntimeException ,定义所有必需的构造函数。你可以说,

@Override
    public void run() {
        try {
            //some code that throws checked exception
        }
        catch(Exception e) {
            throw new UncheckedException(e);
        }
    }

这段代码将编译,因为不需要 throws 在此声明

up9lanfz

up9lanfz5#

您可以改用可调用的:

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());
}

相关问题