Java 异步编程——异步编排(CompletableFuture)

CompletableFuture 是 JDK8 提出的一个支持非阻塞的多功能的 Future,提供了一种强大的异步编程模型,实现了 Future 接口;

在使用 Future 的过程中,大家会发现 Future 有两种方式返回结果的方式

  1. 阻塞方式get()
  2. 轮询方法isDone()

CompletableFuture 接口提供了非常多的方法用于编排异步任务,基本每个方法都有两套实现,Async 版本的函数与非 Async 版本的函数。

  • 若方法不以 Async 结尾,意味着 Action 使用相同的线程执行,而 Async 可能会使用其它的线程去执行(如果使用相同的线程池,也可能会被同一个线程选中执行)。

业务场景

  • 查询商品详情页的逻辑比较复杂, 有些数据还需要远程调用, 必然需要花费更多的时间。

    // 1.获取sku的基本信息 0.5s
    // 2.获取sku的图片信息 0.5s
    // 3.获取sku的促销信息 1s
    // 4.获取spu的所有销售属性 1s
    // 5.获取规格参数组及组下的规格参数 1.5s
    // 6. spu详情 1s
    

    假如商品详情页的每个查询,需要按照标注的时间之和才能完成。即用户需要 5.5s 后才能看到商品详情页的内容。很显然是不能接受的。如果有多个线程同时完成这 6 步操作,也许只需要 1.5s 即可完成响应。

CompletableFuture 使用

  • Future 是 Java 5 添加的类,用来描述一个异步计算的结果。

    虽然 Future 以及相关使用方法提供了异步执行任务的能力,但是对于结果的获取却是很不方便,只能通过阻塞或者轮询的方式得到任务的结果。阻塞的方式显然和我们的异步编程的初衷相违背, 轮询的方式又会耗费无谓的 CPU 资源,而且也不能及时地得到计算结果,为什么不能用观察者设计模式,当计算结果完成及时通知监听者呢?

  • 在 Java 8 中,新增加了一个包含 50 个方法左右的类:CompletableFuture,提供了非常强大的 Future 的扩展功能,可以帮助我们简化异步编程的复杂性,提供了函数式编程的能力,可以通过回调的方式处理计算结果, 并且提供了转换和组合 CompletableFuture 的方法。CompletableFuture 类实现了 Future 接口,所以你还是可以像以前一样通过 get 方法阻塞或者轮询的方式获得结果, 但是这种方式不推荐使用。

  • CompletableFuture 和 FutureTask 同属于 Future 接口的实现类,都可以获取线程的执行结果。

常用方法

  1. 创建异步对象并执行(CompletableFuture)

    CompletableFuture 提供了多种方法来创建异步对象,其中 runAsync 和 supplyAsync 是最常用的方法。

    // 创建一个不返回结果的异步任务,使用默认线程池执行。
    public static CompletableFuture<Void> runAsync(Runnable runnable) {
         
         
        return asyncRunStage(asyncPool, runnable);
    }
    // 创建一个不返回结果的异步任务,使用指定的线程池执行。
    public static CompletableFuture<Void> runAsync(Runnable runnable,Executor executor) {
         
         
        return asyncRunStage(screenExecutor(executor), runnable);
    }
    // 创建一个返回结果的异步任务,使用默认线程池执行。
    public static <U> CompletableFuture<U> supplyAsync(Supplier<U> supplier) {
         
         
        return asyncSupplyStage(asyncPool, supplier);
    }
    // 创建一个返回结果的异步任务,使用指定的线程池执行。
    public static <U> CompletableFuture<U> supplyAsync(Supplier<U> supplier,Executor executor) {
         
         
        return asyncSupplyStage(screenExecutor(executor), supplier);
    }
    
    • runXxxx 都是没有返回结果的,supplyXxx 都是可以获取返回结果的。

    • 可以传入自定义的线程池,否则就用默认的线程池。

    示例:

    // 创建一个线程池
    ExecutorService executor = Executors.newFixedThreadPool(4);
    // 使用 supplyAsync 创建一个返回结果的异步任务
    CompletableFuture<Integer> intFuture = CompletableFuture.supplyAsync(() -> {
         
         
        System.out.println("Calculating result...");
        try {
         
         
            Thread.sleep(1000); // 模拟计算
        } catch (InterruptedException e) {
         
         
            e.printStackTrace();
        }
        return 42; // 返回计算结果
    }, executor);
    // 确保主线程不会提前结束
    intFuture.join();
    // 关闭线程池
    executor.shutdown();
    
  2. thenAccept 方法,计算完成后再操作

    用于在异步任务完成后再执行某个操作,且该操作不返回计算结果。该方法只会在异步任务成功完成时被调用,如果任务失败,则不会执行。

    public CompletableFuture<V
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值