如何在 ScheduledExecutorService 中抛出新的异常?

问题描述 投票:0回答:1

我有以下代码:

public void restart() throws Exception
{
   CompletableFuture<?> delayed = new CompletableFuture<>(); 
   ScheduledExecutorService executorService = 
   Executors.newSingleThreadScheduledExecutor();
   executorService.scheduleWithFixedDelay(() -> 
   {
      try
      {
         throw new RuntimeException("My exception.");
      }
      catch(Exception e)
      {
         delayed.completeExceptionally(e);
      }
   }, 1000L, 150L, TimeUnit.MILLISECONDS));

   delayed.whenCompleteAsync((r, t) -> {
      if (t != null)
      {
         throw new RuntimeException(t);
      }
   });
}

我正试图冒出我将在我的

executorService
中捕获的异常。但是相反发生的是在 try 块中抛出异常,该异常被捕获并且
CompletableFuture
completedExceptionally
。然后重新抛出异常。我希望通过这种方式我能够冒出异常。

但不幸的是,事实并非如此。

delayed
抛出异常但它不会冒泡。最重要的是,由于某种原因,异常循环在此之后立即开始。这是 try 不断抛出异常而 catch 不断捕获但是当然
completableFuture
已经完成所以它不会到那个。

问题是我们如何处理和冒泡异常?

java exception executorservice scheduledexecutorservice
1个回答
1
投票

这对我有用:

public void restart() throws Exception {
    CompletableFuture<?> delayed = new CompletableFuture<>();
    ScheduledExecutorService executorService = Executors.newSingleThreadScheduledExecutor();
    executorService.scheduleWithFixedDelay(() -> {
        try {
            throw new RuntimeException("My exception.");
        } catch(Exception e) {
            delayed.completeExceptionally(e);
        }
    }, 1000L, 150L, TimeUnit.MILLISECONDS);

    try {
        delayed.get();
    } catch (ExecutionException e) {
        throw (Exception) e.getCause();
    }
}

在此修改后的代码中,我们在延迟的

get()
上调用
CompletableFuture
方法,该方法将阻塞直到
CompletableFuture
完成。如果
CompletableFuture
异常完成,
get()
将抛出一个
ExecutionException
并以原始异常为原因。然后我们提取原因并将其作为
Exception
重新抛出。这样,异常就会冒泡到
restart()
方法,并且可以得到适当的处理。

但是如果我们想在不使用阻塞 get 调用的情况下实现它,我们可以使用回调

Consumer<Throwable> callback
如果异常抛出,使用
callback.accept(e);
就像在这个片段中:

    public static void main(String[] args) {
        restart((t) -> System.out.println("Exception occurred: " + t.getMessage()));
    }

    public static void restart(Consumer<Throwable> callback) {
        CompletableFuture.runAsync(() -> {
            try {
                // Code that may throw an exception goes here
                throw new RuntimeException("My exception.");
            } catch (Exception e) {
                callback.accept(e);
            }
        });
    }

© www.soinside.com 2019 - 2024. All rights reserved.