首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
MCP广场
社区首页 >问答首页 >在CompletableFuture中处理java8中的运行时异常

在CompletableFuture中处理java8中的运行时异常
EN

Stack Overflow用户
提问于 2018-01-08 14:42:34
回答 1查看 7.7K关注 0票数 2

下面是我正在使用的示例代码,用于理解在java8中的Cometable前途中的异常处理。如果我们按照doc使用异常方法,异常方法也会捕获甚至运行时异常,并继续到管道中的最后一个块。

如果我们不使用特殊的方法,那么它只是打印运行和退出。

如果我的理解不正确,就纠正我。

问题是,如果我想抛出运行时异常并希望应用程序停止,那么就可以这样说。基本上,如果我抛出运行时异常,它就不应该继续到管道中的下一个块。我该怎么做。任何指示都是有帮助的。

代码语言:javascript
运行
复制
public static void main(String[] args) {
    final CompletableFuture<String> retrieveName = CompletableFuture.supplyAsync(() -> {
        System.out.println("running");
        int i = 0;
        if(i == 0) {
            throw new RuntimeException("ding");
        }
        return "test";
    }).exceptionally(it -> {
        System.out.println(it.getMessage());
        return "empty";
    }).thenApply(it -> {

        System.out.println("last block" + it);
        return "dummy";
    });
}
EN

回答 1

Stack Overflow用户

回答已采纳

发布于 2018-02-03 05:48:21

试试这个:

代码语言:javascript
运行
复制
public static void main(String[] args) {
    try {
        final CompletableFuture<String> retrieveName = CompletableFuture.supplyAsync(() -> {
            System.out.println("running");
            int i = 0;
            if (i == 0) {
                throw new RuntimeException("ding");
            }
            return "test";
        }).exceptionally(it -> {
            if (it.getMessage().contains("ding")) {
                throw (RuntimeException) it;
            }
            System.out.println(it.getMessage());
            return "empty";
        }).thenApply(it -> {
            System.out.println("last block" + it);
            return "dummy";
        });
        retrieveName.join();
    } catch (Exception e) {
        System.out.println("main() exception, cause=" + e.getCause());
    }
}

这是输出:

正在运行 main()异常,cause=java.lang.RuntimeException: ding

我对您的代码做了3个小更改:

  • 把它都包在一次尝试中
  • exceptionally()中为"ding“异常抛出一个exceptionally()
  • retrieveName.join().添加了一个调用从Javadoc到CompletableFuture.join()

公共T加入​() 返回完成后的结果值,否则将抛出(未检查)异常(如果已完成异常)。

基于OP反馈的更新->

假设我想抛出运行时异常并希望应用程序停止。基本上,如果我抛出运行时异常,它就不应该继续到管道中的下一个块。我该怎么做。

只要对代码进行2次更改,就可以实现您想要的结果:

1完全删除exceptionally()回调,以便CompletableFuture (CF)以异常终止。在OP代码中的exceptionally()中,异常被吞没而不是重新抛出,并返回一个CF,因此仍然执行thenApply()方法。

2在main()末尾添加对retrieveName.join()的调用。这是一个阻塞调用,但是由于线程以一个与示例代码不相关的异常结束,所以join()方法将提取抛出的CompletionException.并重新抛出它,并将其包装在一个CompletionException.中。

以下是您修改的代码:

代码语言:javascript
运行
复制
 public static void main(String[] args) {
    final CompletableFuture<String> retrieveName = CompletableFuture.supplyAsync(() -> {
        System.out.println("running");
        int i = 0;
        if(i == 0) {
            throw new RuntimeException("ding");
        }
        return "test";
    }).thenApply(it -> {
        System.out.println("last block" + it);
        return "dummy";
    });
    retrieveName.join();
}

备注:

  • 这不是如何在生产中做事。来自join()的阻塞调用在这里不是一个问题,但可能是一个长期运行的CF。但是,在CF完成之前,显然不能从CF中提取异常,因此join()调用块是有意义的。
  • 请始终记住,main()并不是在与CF相同的线程中运行。
  • 另一种方法(如果可行的话)可能是在exceptionally()中处理所有必要的异常后操作(日志记录等),然后使用适当的返回值(例如:“异常处理!”)而不是传播异常。
  • 您可以通过调用非阻塞的isDone()方法来检查CF是否仍在运行。您还可以检查CF是以异常(isCompletedExceptionally())结尾还是以cancelled(isCancelled​()).结束?
票数 3
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/48152551

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档