Java8新特性-CompletableFuture异步回调

简介

Java8提供了一个新的,具备异步回调能力的工具类**-CompletableFuture**,该类实现了Future接口,同时具备函数式编程的能力。
该类实现了Future接口和CompletionStage两个接口。该类的实例是作为一个异步任务,可以在自己异步执行完成之后触发一些其他的异步任务,从而达到异步回调的效果。

Future接口

Future在java里面,通常用来表示一个异步任务的引用,比如我们将任务提交到线程池里面,会得到一个Future,在Future里面有isDone方法来判断任务是否结束,还有get方法一直阻塞直到任务结束后获取结果,但整体来说,还是同步的,因为需要客户端不断阻塞或者轮询才能知道任务是否结束。
Future的主要缺点:

  1. 不支持手动完成
  2. 不支持进一步的非阻塞调用
  3. 不支持链式调用
  4. 不支持多个Future合并
  5. 不支持异常处理

CompletionStage接口

CompletionStage代表异步计算过程中的某一个阶段,一个阶段完成后可能会进入另一个阶段,一个阶段可以理解为一个子任务,每一个子任务会包装一个java函数式接口实例,表示该子任务所要执行的操作。
每个CompletionStage子任务所包装的可以是一个Function,Consumer或者Runnable函数式接口实例,这三个常用的函数式接口的特点如下:

(1)Function

Function接口的特点是有输入,有输出,包装了Function实例的CompletionStage子任务需要一个输入参数,并会产生一个输出结果到下一步。

(2)Runable

Runable接口的特点是:无输入,无输出,不需要任何输入参数,又不会产生任何输出。

(3)Consumer

接口的特点是:有输入,无输出,需要一个输入参数,但不会产生任何输出。
多个CompletionStage构成了一条任务流水线,一个环节执行完成了可以将结果移交给下一个环节(子任务),多个CompletionStage子任务之间可以使用链式调用,下面是一个简单的例子:
在这里插入图片描述
对以上例子中的ComletionStage子任务说明如下:

  • oneStage是一个CompetionStage子任务,这是一个前提
  • x->square(x)是一个function类型的Lambda表达式,被thenApply()方法包装成了一个CompletionStage子任务,该子任务需要接受一个参数x,然后输出一个x的平方。
  • y-system.out.println(y)是一个Consumer类型的Lambda表达式,被thenAccept()方法包装成了一个CompletionStage子任务,该子任务需要消耗上一个子任务的输出值,但是此任务并没有输出。
  • ()->System.out.println()是一个Runnable类型的Lambda表达式,被thenRun()方法包装成一个CompletionStage子任务,既不消耗上一个子任务的输出,又不产生结果。
    CompletionStage代表异步计算过程中的某一个阶段,一个阶段完成以后可能会触发另一个阶段,虽然一个子任务可以触发其他子任务,但是并不能保证后续子任务的执行顺序。

使用runAsync和supplyAsync创建子任务

CompletableFuture类提供了非常强大的Future的扩展功能来帮助我们简化异步编程的复杂性,提供了函数式编程的能力来帮助我们通过回调的方式处理计算结果,也提供了转换和组合CompletionStage()的方法。
CompletableFuture定义了一组方法用于创建CompletionStage子任务(或者阶段性任务),基础的方法如下:
在这里插入图片描述

CompletableFuture异步编程实战

CompletableFuture中大量的使用了这些函数式接口。
这些声明大量应用于方法的入参中,如:

  • thenApply是Function类型的接口,有输入,有输出
  • thenAccept是Consumer类型的接口,有输入,无输出
    lambda函数正好是作为这些接口的实现。
 public static void main(String[] args) throws ExecutionException, InterruptedException {
        ExecutorService executorService = Executors.newCachedThreadPool();

        executorService.submit(new Callable<Object>() {
            @Override
            public Object call() throws Exception {
                System.out.println("executorService 是否为守护线程 :" + Thread.currentThread().isDaemon());
                return null;
            }
        });
   final CompletableFuture<String> completableFuture = CompletableFuture.supplyAsync(() -> {
            System.out.println("this is lambda supplyAsync");
            System.out.println("supplyAsync 是否为守护线程:" + Thread.currentThread().isDaemon());
            try {
                TimeUnit.SECONDS.sleep(2);
            } catch (InterruptedException e) {
                e.printStackTrace();
             }
            System.out.println("this lambda is executed by forkJoinPool");
            return "result1";
        });
         final CompletableFuture<String> future=CompletableFuture.supplyAsync(()->{
            System.out.println("this is task with executor");
            System.out.println("supplyAsync 使用executorService 时是否为守护线程:"+Thread.currentThread().isDaemon());
            return "result2";
        });
        System.out.println(completableFuture.get());
        System.out.println(future.get());
        executorService.shutdown();
    }
}        

在这里插入图片描述

allOf&anyOf

这两个方法的入参是一个completableFuture组。

  • allOf就是所有任务都完成时返回。但是是个Void的返回值。
  • anyOf是当入参的completableFuture组中有一个任务执行完毕就返回。返回结果是第一个完成的任务的结果。
 CompletableFuture.allOf( accessoriesFuture, catalogueFuture, staffFuture).join();
  CompletableFuture completableFuture = CompletableFuture.anyOf(futureOne, futureTwo);

Join方法

在这里插入图片描述

thenRun

thenRun就是这个任务运行完,再运行下一个任务。感觉像是join了一下。
在这里插入图片描述

thenApply(Function)

这样的就是有入参有返回值类型的。

thenAccept(Consumer)

这样的就是有入参,但是没有返回值的

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值