CompletableFuture并发

本文基于B站视频,深入探讨Java8中的CompletableFuture特性,介绍如何利用它进行异步编程。通过创建和链接异步任务,展示了如何合并独立的任务并处理结果,以及如何优雅地处理异常情况。同时,讲解了不同类型的CompletableFuture方法,如thenApply、thenAccept和thenCompose等,以及它们在处理并发任务时的角色。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >


根据B站系列视频总结

【Java并发·05】CompletableFuture扩展_哔哩哔哩_bilibili


java8中的新特性,为JAVA异步编程提供了可能性。异步意味着任务可以单独运行在其他线程中,并通过回调可以在主线程中得到异步任务的执行状态。

public class CompletableFuture<T> implements Future<T>, CompletionStage<T> {
//实现了Future接口就可以兼容现在有线程池框架
//CompletionStage接口才是异步编程的接口抽象,里面定义多种异步方法    

初体验**supplyAsync()** 开启异步任务

class Solution  {
    public  static void  sleepMillis(long millis){
        try {
            Thread.sleep(millis);
        }catch (InterruptedException e){
            e.printStackTrace();
        }
    }
    public static void printTimeAndThread(String tag){
        String result=new StringJoiner("\t|\t")
                .add(String.valueOf(System.currentTimeMillis()))
                .add(String.valueOf(Thread.currentThread().getId()))
                .add(Thread.currentThread().getName())
                .add(tag)
                .toString();
        System.out.println(result);

    }
    public static void main(String[] args) {
        Solution.printTimeAndThread("小白进入餐厅");
        Solution.printTimeAndThread("点了一盘菜+一碗饭");
        CompletableFuture<String> other=CompletableFuture.supplyAsync(
                ()->{
                    Solution.printTimeAndThread("厨师炒菜");
                    Solution.sleepMillis(200);
                    Solution.printTimeAndThread("厨师盛饭");
                    return "饭菜好了";
                }
        );
        Solution.printTimeAndThread("小白打游戏");
        Solution.printTimeAndThread(other.join());
        Solution.printTimeAndThread("吃饭");
    }
}
打印结果:
1658801729041	|	1	|	main	|	小白进入餐厅
1658801729041	|	1	|	main	|	点了一盘菜+一碗饭
1658801729103	|	1	|	main	|	小白打游戏
1658801729103	|	11	|	ForkJoinPool.commonPool-worker-1	|	厨师炒菜
1658801729316	|	11	|	ForkJoinPool.commonPool-worker-1	|	厨师盛饭
1658801729316	|	1	|	main	|	饭菜好了
1658801729316	|	1	|	main	|	吃饭

如果有多个任务,可以在 CompletableFuture内再用一个CompletableFuture.supplyAsync()。但是CompletableFuture提供了更方便的方法**thenCompose()**。thenCompose()将两个异步任务连接,这两个异步计算之间相互独立,同时第二个又依赖于第一个的结果。

public static void main(String[] args) {
    Solution.printTimeAndThread("小白进入餐厅");
    Solution.printTimeAndThread("点了一盘菜+一碗饭");
    CompletableFuture<String> other=CompletableFuture.supplyAsync(
            ()->{
                Solution.printTimeAndThread("厨师炒菜");
                Solution.sleepMillis(200);
                return "菜好了";   //return传到dish里
            }).thenCompose(dish->CompletableFuture.supplyAsync(()->{
        Solution.printTimeAndThread("服务员盛饭");
        Solution.sleepMillis(100);
        return dish+"饭好了";
    }));
    Solution.printTimeAndThread("小白打游戏");
    Solution.printTimeAndThread(other.join());
    Solution.printTimeAndThread("吃饭");
}

//打印结果:
1658801935231	|	1	|	main	|	小白进入餐厅
1658801935232	|	1	|	main	|	点了一盘菜+一碗饭
1658801935300	|	11	|	ForkJoinPool.commonPool-worker-1	|	厨师炒菜
1658801935301	|	1	|	main	|	小白打游戏
1658801935512	|	11	|	ForkJoinPool.commonPool-worker-1	|	服务员盛饭
1658801935626	|	1	|	main	|	菜好了饭好了
1658801935626	|	1	|	main	|	吃饭

**thenCombine()**合并两个没有依赖关系的CompletableFutures任务。两个任务执行完后,根据两个结果,可以转为一个结果。两个输入一个输出。类似的函数还有thenAcceptBoth()得到前两个任务的结果后没有返回值。runAfterBoth()

**thenApply()**将上一步异步的结果交给后面的funcion.这两个任务是在一个线程中,同步的.一个接收参数一个返回参数。类似的还有thenAccept()会接收前面的参数,但没有返回值。thenRun()不会接收前面的参数且没有返回值

**thenApplyAysn()**将上一步异步的结果交给后面的funcion,异步的。相当于thenCompose()

**applyToEither()**两个运行任务,哪个任务先运行完就将结果给function

exceptionally()可以加在链式操作的任意部分,用于处理异常.类似的方法有handle()参数是BiFunction,无论正常执行还是有异常,handle方法都会返回一个结果。whenComplete()方法和handle()类似,但没有返回值。

.exceptionally(e->{
    Solution.printTimeAndThread(e.getMessage());
    return "处理异常";
})

CompletableFuture的方法有很多是以下形式

xxx(arg)

xxxAsync(arg)

xxxAsync(arg,Executor)

以thenApply()为例:会将两块代码封装成一个任务交给一个线程运行

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值