从runnable中重试检查的异常

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

我从主类执行多个任务:

  1. ExecutorService executor = Executors.newFixedThreadPool(N);
  2. for (int i = 0; i < M; i++) {
  3. executor.execute(task);
  4. }
  5. executor .shutdown();
  6. 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() 允许您抛出选中的异常

  1. 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 ,定义所有必需的构造函数。你可以说,

  1. @Override
  2. public void run() {
  3. try {
  4. //some code that throws checked exception
  5. }
  6. catch(Exception e) {
  7. throw new UncheckedException(e);
  8. }
  9. }

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

up9lanfz

up9lanfz5#

您可以改用可调用的:

  1. Callable<?> task = new Callable<Void> () {
  2. public Void call() throws Exception {
  3. someCodeThatThrowsCheckedExceptions();
  4. return null;
  5. }
  6. }

然后:

  1. Future<?> f = executor.submit(task);
  2. try {
  3. f.get();
  4. } catch (ExecutionException e) {
  5. System.out.println("task threw exception: " + e.getCause().getMessage());
  6. }

相关问题