线程的异步调用 CompletableFuture简介及使用

Posted 若曦`

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了线程的异步调用 CompletableFuture简介及使用相关的知识,希望对你有一定的参考价值。

1. CompletableFuture简介


在源码中可以看出,CompletableFuture是一个泛型类,实现了Future接口和CompletionStage接口

一个completetableFuture就代表了一个任务,因为继承了上述两个接口的关系,可以完成一些线程的异步调用操作

异步调用的简要介绍可以看这位大佬的博客 JAVA的异步调用

completionStage接口的作用:支持任务完成时触发的函数和操作

Future接口的作用

Future 是异步计算结果的容器接口,它提供了在等待异步计算完成时检查计算是否完成的状态

实现Future接口代表 在异步计算完成后获取计算结果只能通过 get() 方法获取结果,如果异步计算没有完成则阻塞当前线程,也可以在异步计算完成前使用 cancel() 方法取消异步计算的线程

2. CompletableFuture的使用

(1) 用作线程的监视器

其实本质是利用Future接口的方法get(),使用complete()向get()方法传值

注意点:get()方法相当于是阻塞了主方法的线程,当使用complete()方法后,会激活get()方法所在的线程

   // 使用方式1: 监视线程的执行 可以在结束时传递一个返回值
        CompletableFuture completableFuture = new CompletableFuture();
        new Thread(()->
            System.out.println("这是CompletableFuture监视的线程");
            System.out.println("线程任务结束,使用CompletableFuture 来传递线程任务结束的返回值");
            System.out.println("--------------");
            // 步骤1.在线程中使用complete()函数传递结束值
            completableFuture.complete("线程任务结束");
        ).start();
        try 
            // 步骤2. 在其他线程中使用get()获取结束的返回值
            System.out.println(completableFuture.get());
         catch (InterruptedException e) 
            e.printStackTrace();
         catch (ExecutionException e) 
            e.printStackTrace();
        

(2) 用于异步回调

方式有runAsync 或 supplyAsync (内部都是一个Runnable函数式接口)

使用步骤

① 创建一个线程池(也可以不创建)
② 创建一个CompletableFuture对象,内置一个runAsync()的任务或supplyAsync()任务
③ 可以指定任务注册的线程池,不写则默认是ForkJoinPool

注意点

① 返回值
runAsync() 没有返回值
supplyAsync() 有返回值
② 是否是守护线程
使用默认的ForkJoinPool,是守护线程
使用自己创建的线程池,不是守护线程
③ 线程池开启后,要记得关闭线程池服务
executorService.shutdown();
④ 任务的结束还是需要get()方法去控制

代码示例

public static void myTest() throws ExecutionException, InterruptedException 
        // 使用方式2: 用于异步回调 方式有runAsync 或 supplyAsync
        // 1. 创建一个缓存线程池
        ExecutorService executorService = Executors.newCachedThreadPool();
        // 2. 开启一个runAsync(异步执行任务)
        CompletableFuture<Void> completableFuture1 = CompletableFuture.runAsync(()->
            System.out.println("runAsync使用的的是默认的FrokJoinPool,使用该线程池,是否是守护线程--"+Thread.currentThread().isDaemon());
        );
        System.out.println("任务的返回值是---"+completableFuture1.get());
        System.out.println("runAsync异步方式执行结束");

        // 3. 开启一个supplyAsync(异步提供者任务)
        CompletableFuture completableFuture2 = CompletableFuture.supplyAsync(()->
            System.out.println("runAsync使用的是缓存线程池executorService,使用该线程池,是否是守护线程--"+Thread.currentThread().isDaemon());
            return "---这是supplyAsync执行的返回值";
        ,executorService); // 4. 传入参数:缓存线程池
        System.out.println("==================");
        System.out.println("任务的返回值是---"+completableFuture2.get());
        System.out.println("supplyAsync异步提供者方式调用结束");
        System.out.println("==================");
        // 关闭线程池服务
        executorService.shutdown();
    

以上是关于线程的异步调用 CompletableFuture简介及使用的主要内容,如果未能解决你的问题,请参考以下文章

JUC - 多线程之ForkJoin;异步调用CompletableFuture

java中异步调用,Callable,Future,FutureTask,CompletableFuture如何使用

java中异步调用,Callable,Future,FutureTask,CompletableFuture如何使用

异步回调CompletableFuture

奇淫巧技,CompletableFuture 异步多线程是真的优雅

CompletableFuture