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

查看:505
本文介绍了使用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.
    }
}

现在我想将此异常处理为 y 在我的 biConsumer 中。这将帮助我处理单个函数内的结果以及异常(如果有的话)( 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 实例来设置异常,而工厂方法需要供应商,鸡肉和鸡蛋。

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 <的文档/ code> 说:

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:


  • All async methods without an explicit Executor argument are performed using the ForkJoinPool.commonPool()

因此您知道以下代码将直接处理已检查的异常时显示 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

如果您希望遵守此约定以使解决方案更像原始 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天全站免登陆