CompletableFuture

感情迁移 提交于 2019-12-05 18:08:08

感觉好久没有更新点东西了,自己都看不下去了啊……

前言

CompletableFuture 是 java8 提供的功能,java8至今已经挺久了,所以也不能算新东西,不过之前android的开发不太用到java8的特性,就连stream也用的是rxjava。

Future

在理解CompletableFuture,先理解Future还是非常重要的。因为CompletableFuture算是Future的增强版。 Future用于表示一个带返回值的异步计算过程。内部方法包括获取返回值,cancel任务,查看任务是否完成等。 Future有几个继承

  • RunnableFuture 同时继承了Runnable和 Future的一个接口。最常用的FutureTask就是这个接口的实现类。ExecutorThreadPool调用submit方法就会创建一个FutureTask对象的返回。
  • ScheduledFuture 继承了Future 和 Delayed 接口的一个接口,用于表示一个带delay效果的Future。然后RunnableScheduledFuture 进一步继承了ScheduledFuture 和 RunnableFuture,实际上就表示一个带有delay和周期运行功能的 RunnableFuture。他的最终实现类就是ScheduledFutureTask. 通过 ScheduledThreadPoolExecutor 线程池,调用schedule方法,实际返回的就是一个 ScheduledFutureTask。

Future还有几种继承类型,这个就和每一个知识点绑定来说,比如CompletableFuture,实际上也是Future的继承者。

CompletableFuture

实际上,CompletableFuture 的核心思想是函数式编程,这在java8中的流式机制stream中也有体现。在以前android开发中,承担起函数式开发重任的基础库是rxjava,不过在服务端开发中这个库并不是很常用,直接使用java8的特性就能实现大部分流操作。

CompletionStage

CompletionStage 类是CompletableFuture任务链的中间类,表示一个阶段状态,CompletableFuture本身就继承了这个接口,实际使用中我们很少直接用到这个类。不过CompletableFuture的流式功能就是通过这个类定义的,比如thenAccept等这些方法。

runAsync 和 supplyAsync方法

CompletableFuture 提供了四个静态方法来创建一个异步操作。

public 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)

没有指定Executor的方法会使用ForkJoinPool.commonPool() 作为它的线程池执行异步代码。如果指定线程池,则使用指定的线程池运行。以下所有的方法都类同。

  • runAsync方法不支持返回值。
  • supplyAsync可以支持返回值。
//无返回值
public static void runAsync() throws Exception {
    CompletableFuture<Void> future = CompletableFuture.runAsync(() -> {
        try {
            TimeUnit.SECONDS.sleep(1);
        } catch (InterruptedException e) {
        }
        System.out.println("run end ...");
    });

    future.get();
}

//有返回值
public static void supplyAsync() throws Exception {
    CompletableFuture<Long> future = CompletableFuture.supplyAsync(() -> {
        try {
            TimeUnit.SECONDS.sleep(1);
        } catch (InterruptedException e) {
        }
        System.out.println("run end ...");
        return System.currentTimeMillis();
    });

    long time = future.get();
    System.out.println("time = "+time);
}

流式方法

在开启一个CompleteFuture之后,后续就可以使用流式方法了,比如thenAccept表示消费处理结果。

public static void thenAccept() throws Exception{
    CompletableFuture<Void> future = CompletableFuture.supplyAsync(new Supplier<Integer>() {
        @Override
        public Integer get() {
            return new Random().nextInt(10);
        }
    }).thenAccept(integer -> {
        System.out.println(integer);
    });
    future.get();
}

thenAccept消费了前一步返回的结果。顺带一提,还有一个thenAcceptAsync.

  • thenAccept:是执行当前任务的线程执行继续执行 thenAccept 的任务。
  • thenAcceptAsync:是执行把 thenAcceptAsync 这个任务继续提交给线程池来进行执行。

流式还有不少方法,不过没必要穷举说明,需要用到的时候查一下就好了。

参考

https://www.jianshu.com/p/6bac52527ca4

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!