使用 CompletableFuture 处理 Java 8 供应商异常 [英] Java 8 Supplier Exception handling with CompletableFuture

查看:36
本文介绍了使用 CompletableFuture 处理 Java 8 供应商异常的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

考虑下面的代码

public class TestCompletableFuture {

    BiConsumer<Integer, Throwable> biConsumer = (x,y) -> {
        System.out.println(x);
        System.out.println(y);
    };

    public static void main(String args[]) {
        TestCompletableFuture testF = new TestCompletableFuture();
        testF.start();      
    }

    public void start() {
        Supplier<Integer> numberSupplier = new Supplier<Integer>() {
            @Override
            public Integer get() {
                return SupplyNumbers.sendNumbers();                     
            }
        };
        CompletableFuture<Integer> testFuture = CompletableFuture.supplyAsync(numberSupplier).whenComplete(biConsumer);         
    }       
}

class SupplyNumbers {
    public static Integer sendNumbers(){
        return 25; // just for working sake its not  correct.
    }
}

上面的东西工作正常.但是 sendNumbers 也可以在我的情况下抛出一个已检查的异常,例如:

The above thing works fine. However sendNumbers could also throw a checked exception in my case, like:

class SupplyNumbers {
    public static Integer sendNumbers() throws Exception {
        return 25; // just for working sake its not  correct.
    }
}

现在我想在我的 biConsumer 中将这个异常作为 y 处理.这将帮助我处理单个函数 (biConsumer) 内的结果和异常(如果有).

Now I want to handle this exception as y in my biConsumer. This will help me in handling the result as well as exception (if any) inside a single function (biConsumer).

有什么想法吗?我可以在这里使用 CompletableFuture.exceptionally(fn) 或其他任何东西吗?

Any ideas? Can I use CompletableFuture.exceptionally(fn) here or anything else?

推荐答案

当您想要处理已检查异常时,使用标准函数式接口的工厂方法没有帮助.当您将捕获异常的代码插入到 lambda 表达式中时,您会遇到问题:catch 子句需要 CompletableFuture 实例来设置异常,而工厂方法需要 Supplier,鸡和蛋.

The factory methods using the standard functional interfaces aren’t helpful when you want to handle checked exceptions. When you insert code catching the exception into the lambda expression, you have the problem that the catch clause needs the CompletableFuture instance to set the exception while the factory method needs the Supplier, chicken-and-egg.

您可以使用类的实例字段来允许在创建后进行更改,但最终,生成的代码并不干净,而且比基于 Executor 的直接解决方案更复杂.CompletableFuture 说:

You could use an instance field of a class to allow mutation after creation, but in the end, the resulting code isn’t clean and more complicated that a straight-forward Executor-based solution. The documentation of CompletableFuture says:

所以您知道以下代码将显示 CompletableFuture.supplyAsync(Supplier) 的标准行为,同时直接处理已检查的异常:

So you know the following code will show the standard behavior of CompletableFuture.supplyAsync(Supplier) while handling checked exceptions straight-forward:

CompletableFuture<Integer> f=new CompletableFuture<>();
ForkJoinPool.commonPool().submit(()-> {
  try { f.complete(SupplyNumbers.sendNumbers()); }
  catch(Exception ex) { f.completeExceptionally(ex); }
});

文档还说:

... 为了简化监控、调试和跟踪,所有生成的异步任务都是标记接口的实例 CompletableFuture.AsynchronousCompletionTask.

… To simplify monitoring, debugging, and tracking, all generated asynchronous tasks are instances of the marker interface CompletableFuture.AsynchronousCompletionTask.

如果您想遵守此约定以使解决方案的行为更像原始 supplyAsync 方法,请将代码更改为:

If you want to adhere to this convention to make the solution even more behaving like the original supplyAsync method, change the code to:

CompletableFuture<Integer> f=new CompletableFuture<>();
ForkJoinPool.commonPool().submit(
  (Runnable&CompletableFuture.AsynchronousCompletionTask)()-> {
    try { f.complete(SupplyNumbers.sendNumbers()); }
    catch(Exception ex) { f.completeExceptionally(ex); }
});

这篇关于使用 CompletableFuture 处理 Java 8 供应商异常的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆