欢迎光临
我们一直在努力

24 | CompletableFuture:异步编程没那么难

第二部分:并发工具类

24 | CompletableFuture:异步编程没那么难

文章目录

  • 第二部分:并发工具类
    • 24 | CompletableFuture:异步编程没那么难
      • CompletableFuture 的核心优势
      • 创建 CompletableFuture 对象
      • 如何理解 CompletionStage 接口
        • 1. `描述串行关系`
        • 2. `描述 AND 汇聚关系`
        • 3. `描述 OR 汇聚关系`
        • 4. `异常处理`
      • 总结
      • 课后思考
      • 课后精彩留言

在这里插入图片描述

在这里插入图片描述
前面我们不止一次提到,用多线程优化性能,其实不过就是将串行操作变成并行操作。如果仔细观察,你还会发现在串行转换成并行的过程中,一定会涉及到异步化,例如下面的示例代码,现在是串行的,为了提升性能,我们得把它们并行化,那具体实施起来该怎么做呢?

//以下两个方法都是耗时操作
doBizA();
doBizB();

还是挺简单的,就像下面代码中这样,创建两个子线程去执行就可以了。你会发现下面的并行方案,主线程无需等待 doBizA() 和 doBizB() 的执行结果,也就是说 doBizA() 和 doBizB() 两个操作已经被异步化了。

new Thread(()->doBizA())
.start();
new Thread(()->doBizB())
.start();

异步化,是并行方案得以实施的基础,更深入地讲其实就是:利用多线程优化性能这个核心方案得以实施的基础。看到这里,相信你应该就能理解异步编程最近几年为什么会大火了,因为优化性能是互联网大厂的一个核心需求啊。Java 在 1.8 版本提供了 CompletableFuture 来支持异步编程,CompletableFuture 有可能是你见过的最复杂的工具类了,不过功能也着实让人感到震撼。

CompletableFuture 的核心优势

为了领略 CompletableFuture 异步编程的优势,这里我们用 CompletableFuture 重新实现前面曾提及的烧水泡茶程序。首先还是需要先完成分工方案,在下面的程序中,我们分了 3 个任务:任务 1 负责洗水壶、烧开水,任务 2 负责洗茶壶、洗茶杯和拿茶叶,任务 3 负责泡茶。其中任务 3 要等待任务 1 和任务 2 都完成后才能开始。这个分工如下图所示。 在这里插入图片描述 下面是代码实现,你先略过 runAsync()、supplyAsync()、thenCombine() 这些不太熟悉的方法,从大局上看,你会发现:

  • 无需手工维护线程,没有繁琐的手工维护线程的工作,给任务分配线程的工作也不需要我们关注;
  • 语义更清晰,例如 f3 = f1.thenCombine(f2, ()->{}) 能够清晰地表述“任务 3 要等待任务 1 和任务 2 都完成后才能开始”;
  • 代码更简练并且专注于业务逻辑,几乎所有代码都是业务逻辑相关的。
  • //任务1:洗水壶->烧开水
    CompletableFuture<Void> f1 =
    CompletableFuture.runAsync(()->{
    System.out.println(\”T1:洗水壶…\”);
    sleep(1, TimeUnit.SECONDS);

    System.out.println(\”T1:烧开水…\”);
    sleep(15, TimeUnit.SECONDS);
    });
    //任务2:洗茶壶->洗茶杯->拿茶叶
    CompletableFuture<String> f2 =
    CompletableFuture.supplyAsync(()->{
    System.out.println(\”T2:洗茶壶…\”);
    sleep(1, TimeUnit.SECONDS);

    System.out.println(\”T2:洗茶杯…\”);
    sleep(2, TimeUnit.SECONDS);

    System.out.println(\”T2:拿茶叶…\”);
    sleep(1, TimeUnit.SECONDS);
    return \”龙井\”;
    });
    //任务3:任务1和任务2完成后执行:泡茶
    CompletableFuture<String> f3 =
    f1.thenCombine(f2, (__, tf)->{
    System.out.println(\”T1:拿到茶叶:\” + tf);
    System.out.println(\”T1:泡茶…\”);
    return \”上茶:\” + tf;
    });
    //等待任务3执行结果
    System.out.println(f3.join());

    void sleep(int t, TimeUnit u) {
    try {
    u.sleep(t);
    }catch(InterruptedException e){}
    }
    // 一次执行结果:
    T1:洗水壶…
    T2:洗茶壶…
    T1:烧开水…
    T2:洗茶杯…

    赞(0)
    未经允许不得转载:171主机测评 » 24 | CompletableFuture:异步编程没那么难
    分享到: 更多 (0)

    评论 抢沙发

    • 昵称 (必填)
    • 邮箱 (必填)
    • 网址