CompletableFuture异步编排的使用

一、问题背景

在查询商品详情信息时比较复杂,其中可能还涉及到远程调用,这会消耗很多的时间,如:

// 获取商品基本信息      0.5s
// 获取商品图片信息      1s
// 获取商品的销售属性    1s
// 获取商品的规格参数    1s
// ...

那么这个查询用户需要3.5秒后才能看到页面数据,如果有多个线程同时完成这4个步骤,也许只需要1秒就能看到数据
而在Java8后提供了一个CompletableFuture来帮我们实现这个功能,CompletableFuture,提供了非常强大的 Future 的扩展功能,可以帮助我们简化异步编程的复杂性,提供了函数式编程的能力,可以通过回调的方式处理计算结果,并且提供了转换和组合 CompletableFuture 的方法。 CompletableFuture 类实现了 Future 接口,所以你还是可以像以前一样通过get方法阻塞或者轮询的方式获得结果

创建异步对象

static CompletableFuture<Void> runAsync(Runnable runnable)
public static CompletableFuture<Void> runAsync(Runnable runnable, Executor executor)
public static <U> CompletableFuture<U> supplyAsync(Supplier<U> supplier)
public static <U> CompletableFuture<U> supplyAsync(Supplier<U> supplier, Executor executor)

runAsync都是没有返回结果的,supplyAsync都是可以获取返回结果的
可以传入自定义的线程池,否则就用默认的线程池;

线程串行化

public <U> CompletableFuture<U> thenApply(Function<? super T,? extends U> fn)
public <U> CompletableFuture<U> thenApplyAsync(Function<? super T,? extends U> fn)
public <U> CompletableFuture<U> thenApplyAsync(Function<? super T,? extends U> fn, Executor executor)

Function<? super T,? extends U> T:上一个任务返回结果的类型 U:当前任务的返回值类型

多任务组合

public static CompletableFuture<Void> allOf(CompletableFuture<?>... cfs)
public static CompletableFuture<Object> anyOf(CompletableFuture<?>... cfs)

allOf:所有任务都完成,anyOf:任何一个任务执行完成
下面就通过具体代码来演示如何使用:

无返回值runAsync
public class Test {

    /** 自定义一个线程池 */
    private static final ThreadPoolExecutor SERVICE = new ThreadPoolExecutor(
            10, 20,60, TimeUnit.SECONDS,
            new LinkedBlockingDeque<>(60));

    public static void main(String[] args) throws ExecutionException, InterruptedException {
        // 无返回值
        CompletableFuture<Void> voidCompletableFuture = CompletableFuture.runAsync(() -> {
            System.out.println(Thread.currentThread().getName() + "---->无返回值异步开始");
        }, SERVICE);
    }
}
获取返回结果supplyAsync
public static void main(String[] args) throws ExecutionException, InterruptedException {
        // 有返回值
        CompletableFuture<Integer> uCompletableFuture = CompletableFuture.supplyAsync(() -> {
            System.out.println("---->返回值异步开始");
            int i = 10 / 0;
            return 1;
        }, SERVICE).whenComplete((res, exeption) -> {
            // 异步完成后的回调
            System.out.println("结果:" + res + "\t异常:" + exeption);
        }).exceptionally(exeption -> {
            // 可以进一步处理异常,改变返回值
            System.out.println("异常:" + exeption);
            return 20;
        });
    }

使用handle接收

public static void main(String[] args) throws ExecutionException, InterruptedException {
        CompletableFuture<Integer> uCompletableFuture = CompletableFuture.supplyAsync(() -> {
            System.out.println("---->返回值异步开始");
            int i = 10 / 0;
            return 1;
        }, SERVICE).handle((res, exeption) -> {
            if (exeption != null) {
                System.out.println("异常原因:" + exeption);
                return -1;
            }else {
                System.out.println("结果为:" + res);
                return res;
            }
        });
    }
线程串行化方法
public static void main(String[] args) throws ExecutionException, InterruptedException {
        /*
         * 不能接收上一步的结果,也没有返回值
         * .thenRunAsync(() -> {
         *             System.out.println("任务二启动了....");
         *         }, SERVICE)
         *
         *  能接收上一步的结果有返回值
         *  .thenApplyAsync((res) -> {
         *             System.out.println("上一步的结果:" + res);
         *             return "1";
         *         }, SERVICE);
         *
         *  能接收上一步的结果但没有返回值
         *  .thenAcceptAsync((res) -> {
         *             System.out.println("上一步的结果为:" + res);
         *         }, SERVICE)
         */
        CompletableFuture<String> future = CompletableFuture.supplyAsync(() -> {
            System.out.println("---->返回值异步开始");
            // int i = 10 / 0;
            return 1;
        }, SERVICE).thenApplyAsync((res) -> {
            System.out.println("上一步的结果:" + res);
            return "1";
        }, SERVICE);
    }
public static void main(String[] args) throws ExecutionException, InterruptedException {
        // 第一个任务
        CompletableFuture<Integer> future01 = CompletableFuture.supplyAsync(() -> {
            System.out.println("---->任务1异步开始...");
            return 1;
        }, SERVICE);
        // 第二个任务
        CompletableFuture<Integer> future02 = CompletableFuture.supplyAsync(() -> {
            System.out.println("---->任务2异步开始....");
            try {
                Thread.sleep(2000);
                System.out.println("任务二结束...");
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
            return 2;
        }, SERVICE);

        // 不能接收前两个的结果,也无返回值
        future01.runAfterBothAsync(future02, () -> System.out.println("任务三开始"), SERVICE);
        // 能接收前两个的结果,无返回值
        future01.thenAcceptBothAsync(future02, (res1, res2) -> {
            System.out.println("任务一的结果为:" + res1);
            System.out.println("任务二的结果为:" + res2);
        }, SERVICE);
        // 能接收前两个的结果,有返回值
        CompletableFuture<String> future03 = future01.thenCombineAsync(future02, (res1, res2) -> {
            return res1 + res2 + "";
        }, SERVICE);

        /*
          两个任务只要有一个完成,就执行下一步
         */
        
        // 不接收上一步结果,也无返回值
        future01.runAfterEitherAsync(future02, () -> System.out.println("任务三开始"), SERVICE);
        // 接收上一步结果,无返回值,(任务一和任务二的返回值结果应该同一类型)
        future01.acceptEitherAsync(future02, (res1) -> {
        }, SERVICE);
        // 接收上一步的结果,有返回值
        future01.applyToEitherAsync(future01, (res)-> {
            return "q";
        }, SERVICE);
    }
任务组合
public static void main(String[] args) throws ExecutionException, InterruptedException {
        /*
            多任务组合
            allOf:所有都完成
            anyOf:只要一个完成
         */
        CompletableFuture<Integer> future01 = CompletableFuture.supplyAsync(() -> {
            System.out.println("---->任务1异步开始...");
            return 1;
        }, SERVICE);

        CompletableFuture<String> future02 = CompletableFuture.supplyAsync(() -> {
            System.out.println("---->任务2异步开始....");
            try {
                Thread.sleep(2000);
                System.out.println("任务二结束...");
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
            return "2";
        }, SERVICE);
        
        CompletableFuture<Void> allOf = CompletableFuture.allOf(future01, future02);
        // 获取执行结果,会阻塞
        allOf.get();
        System.out.println("1:" + future01.get() + "\t2:" + future02.get());
        CompletableFuture<Object> anyOf = CompletableFuture.anyOf(future01, future02);
        // 返回的是先执行完返回的数据
        Object o = anyOf.get();

        System.out.println("main--->end...");
    }
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

coder-ren

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值