Rethrow检查了Runnable的异常

时间:2013-06-06 08:48:42

标签: java multithreading exception runnable

我从我的主类执行多个任务:

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块来包围调用。
所以,我的主类没有办法知道抛出了异常。

我该如何解决这个问题?

5 个答案:

答案 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>来克服返回

您需要做什么:

  1. 让您的任务实施Callable<Void>而不是Runnable - 将void run()更改为Void call() throws Exception。无需尝试/捕获已检查的异常。添加return null;语句。
  2. 使用Future<Void> checkableResult = ExecutorService.submit(Callable<Void>)
  3. 您可以通过调用checkableResult.get()来检查是否引发了异常,如果有get(),则会引发ExecutionExceptiongetCause()可以检索原始异常。特别注意Callable.isDone()是阻塞的 - 所以定期检查Runnable可能就是你想要的(否则你也可以在同一个线程中运行它)。
  4. 另一种选择是在volatile boolean isDonevolatile Exception exception和{{1}})中构建功能 - 但为什么要重新发明轮子?