lambda表达式之CompletableFuture

最近阅读了java 8实战和java 8 函数式编程两本书,并参照书中的例子进行了编程练习,代码放在了GitHub上。对stream流的串行,并行,和一些流的操作函数进行了实操。也都是比较容易上手的。不过对于CompletableFuture类的使用,书中对其方法和应用讲的较为简单,自己在实际应用中遇到好多新的需求,经常需要再查资料来解决,现在把它们记录下来,加深印象。
#何时使用CompletableFuture

  • 进行计算密集型的操作,并且没有I/O,那么推荐使用Stream接口,因为实现简单,同时效率也可能是最高的(如果所有的线程都是计算密集型的,那就没有必要创建比处理器核数更多的线程)。
  • 如果并行操作设计等到I/O的操作(网络连接,请求等),那么使用CompletableFuture灵活性更好,通过控制线程数量来优化程序的运行。
  • CompletableFuture可以对流进行并行计算,但并行处理数量为计算机CPU数量,加入线程池可以并行加并发,提高效率。参见代码test3和test4
    #简单的异步执行
    ##无返回值
CompletableFuture<Integer> future = CompletableFuture.runAsync(()->accountDao.update(account));

有返回值

CompletableFuture<Integer> future = CompletableFuture.supplyAsync(()->accountDao.update(account));

以Async结尾的方法表示会另起一个线程执行,默认使用ForkJoinPool.commonPool(),也可以指定自定义线程池。

public static <U> CompletableFuture<U> 	supplyAsync(Supplier<U> supplier, Executor executor)

#得到异步处理结果,进一步计算

thenAccept

CompletableFuture<Void> voidFuture = CompletableFuture.supplyAsync(() -> accountDao.update(account))
                                    .thenAccept(result -> {
                                        if (result != 1) {
                                            throw new RuntimeException("账户更新写入数据库失败");
                                        }
                                    });

纯消费,异步执行方法为thenAcceptAsync

thenApply

CompletableFuture<User> userFuture = CompletableFuture.supplyAsync(() -> accountDao.getAccountById(id))
                                    .thenApply(account -> {
                                        User user = new User();
                                        user.setName = account.getName();
                                        return new user;
                                    });

该方法可以对返回future的类型进行转换

使用异步结果进行另一个异步操作

    CompletableFuture<List<User>> userListFuture = CompletableFuture.supplyAsync(() -> accountDao.getAccountById(id))
                .thenCompose(
                        account -> CompletableFuture.supplyAsync(() -> accountDao.getUserListByName(account.getName()))
                );

该方法与thenApply都使用了上一个异步结果,区别是thenCompose返回一个新的future,而thenApply返回一个对象替换原future的泛型。

whenComplete响应结果或异常

方法声明为

public CompletableFuture<T> whenComplete(BiConsumer<? super T,? super Throwable> action)

简单示例:

CompletableFuture<Integer> resultFuture = CompletableFuture.supplyAsync(() -> accountDao.update(account))
                                    .whenComplete(result,ex) -> {
                                        if(ex!=null){
                                            ex.printStackTrace();
                                        }
                                        if (result != 1) {
                                            throw new RuntimeException("账户更新写入数据库失败");
                                        }
                                    });

whenComplete不会改变原future的结果,还可以在其上调用其他方法。

handle 处理异常

  CompletableFuture.supplyAsync(()->{throw new RuntimeException("test");}).handle((result,ex)->{
            if (ex!=null){
                return null;
            }
            return result;
        });

与whenComplete不同的是,handle的c入参是BiFunction类型,可以对结果类型进行转换。

exceptionally 只处理异常

whenComplete和handle都是既响应正常完成也响应异常,如果只对异常感兴趣,可以使用exceptionally。其声明为:

public CompletableFuture<T> exceptionally(
    Function<Throwable, ? extends T> fn)

后面还想写CompletableFuture对两个以及多个future处理,涉及到的方法为thenAcceptBoth、thenCombine、runAfterBoth、runAfterEither、applyToEither、acceptEither、allOf、anyOf。不过这篇博客讲的更为仔细,就不赘述了。

  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值