zoukankan      html  css  js  c++  java
  • Lagom学习 四 CompletionStage

    Future: Java 8 之前的 Java 版本功能较弱,仅支持两种用法:要么检查 future 是否已经完成,要么等待 future 完成;

    Java 8 增加了 CompletableFuture<T> 类,它实现了新的 CompletionStage<T> 接口,并对 Future<T>进行了扩展。(都包含在 java.util.concurrent 包中。)CompletionStage 代表异步计算中的一个阶段或步骤。该接口定义了多种不同的方式,将CompletionStage 实例与其他实例或代码链接在一起,比如完成时调用的方法(一共 59 种方法,比Future 接口中的 5 种方法要多得多。)

    CompletionStage 的接口一般都返回新的CompletionStage,表示执行完一些逻辑后,生成新的CompletionStage,构成链式的阶段型的操作。

    Java 1.5 有了 Future, 可谓是跨了一大步,继而 Java 1.8 新加入一个 Future 的实现 CompletableFuture, 从此线程与线程之间可以愉快的对话了。最初两个线程间的协调我采用过 Object 的  wait() 和 notify() , Thread 的 join() 方法,那可算是很低级的 API 了,是否很多 Java 程序都不知道它们的存在,或根本没用过它们。

    如果是简单的等待所有线程完成可使用 Java 1.5 的 CountDownLatch, 这里有一篇介绍 CountDownLatch 协调线程, 就是实现的 waitAll(threads) 功能。而 Java 8 的 CompletableFuture 的功能就多去,可简单使用它实现异步方法。虽说 CompletableFuture 实现了 Future 接口,但它多数方法源自于 CompletionStage, 所以还里氏代换,用 Future 来引用 CompletableFuture 实例就很牵强了; 这也是为什么 PlayFramework 自 2.5 开始直接暴露的类型是 CompletionStage 而非其他两个。

    顾名思义,CompletableFuture 代表着一个 Future 完成后该干点什么,具体大致有:

    1. Future 完成后执行动作,或求取下一个 Future 的值。then...
    2. 多个 Future 的协调; 同时完成该怎么,其中一个完成该如何。allOf, anyOf

    CompletableFuture 有太多太多的方法,并伴有 async 与 非 async 两个版本。试想一下,如过不用 Future 或  CompletableFuture, 想要实现等待某个线程完成之后才做后续的事,可以用join或wait等。但是CompletableFuture更好。

    同步和异步:

    package completeFutture;
    
    import java.util.concurrent.CompletableFuture;
    
    public class Test {
        public static void main(String[] args) {
            CompletableFuture<Double> futurePrice = getPriceAsync();
            //do anything you want, 当前线程不被阻塞
            System.out.println(111);
            //线程任务完成的话,执行回调函数,不阻塞后续操作
            futurePrice.whenComplete((aDouble, throwable) -> {
                System.out.println(aDouble);
                //do something else
            });
            System.out.println(222);
        }
    
        static CompletableFuture<Double> getPriceAsync() {
            CompletableFuture<Double> futurePrice = new CompletableFuture<>();
            new Thread(() -> {
                try {
                    Thread.sleep(5000);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
                futurePrice.complete(23.55);
            }).start();
            return futurePrice;
        }
    }

    输出结果:

    111
    222
    23.55

    getPriceAsync() 模拟一个很耗时的操作,因为其行为是在一个线程中做的,所以不会阻塞打印 111的程序;
    getPriceAsync()中线程在执行完后才会把23.55赋值给futurePrice,所以futurePrice.whenComplete..要等待futurePrice.complete(23.55)执行完才会执行whenComplete。
    注意whenComplete内部也是开新的线程执行,所以不会阻塞当前代码,System.out.println(222)会被执行,最后当futurePrice.complete(23.55)执行完后,
     System.out.println(aDouble)会执行


  • 相关阅读:
    .NET牛人应该知道些什么
    ASP.NET常用的分页
    获取字符串长度
    去掉网页的滚动条
    GridView动态生成字段常见问题及解决方法
    PagesSection.ValidateRequest 属性
    我刚刚做了一个艰难的决定
    Jquery UI Dialog 对话框学习
    c语言病毒分析(转)
    不用不熟悉的工具和方法
  • 原文地址:https://www.cnblogs.com/liufei1983/p/8481251.html
Copyright © 2011-2022 走看看