CompletableFuture的使用方式及常用的API

介绍

  1. JDK1.8之前,使用的是Futrue来创建异步线程,这样做比较麻烦。JDK1.8之后,出现了CompletableFuture,内含多种API,使用起来很方便

方法API, CompletabelFuture的静态方法,执行异步任务的API

// 1. 无返回值,默认能使用ForkJoinPool.commonPool() 作为他的线程池执行异步代码
public static CompletableFuture<Void> runAsync(Runnable runnable)

// 2. 无返回值,可以自定义线程池
public static CompletableFuture<Void> runAsync(Runnable runnable)

// 3. 有返回值,默认使用ForkJoinPool.commonPool() 作为他的线程池执行异步代码
public static <U> CompletableFuturn<U> supplyAsync(Supplier<U> supplier)

// 4. 有返回值, 可以自定义线程池
public static <U> CompletableFuture<U> supplyAsync(Supplier<U> supplier, Executor executor)

CompletableFuture对象,获取结果API

// 1. 如果返回值没有返回,则一直阻塞
V get();

// 2. 设置等待超时时间
V get(Long timeout, Timeout unit)

// 3. 有返回值就返回,线程抛出异常就返回设置的默认值
T getNow(T defaultValue);

CompletableFuture对象,其他重点API

// 1. 无返回值,当前任务正常完成以后执行,当前任务的执行结果可以作为下一个任务的输入参数
thenAccept

// 2. 有返回值,当前任务正常完成以后,当前任务执行的结果会作为下一个任务的输入参数
thenApply

// 3. 对不关心上一步的计算结果,执行下一个操作
thenRun

案例

1. 【有返回值】,默认使用ForkJoinPool.commonPool() 作为他的线程池执行异步代码

    /**
     * 【有返回值】,【supplyAsync】测试,默认使用ForkJoinPool.commonPool() 作为他的线程池执行异步代码
     */
    @Test
    public void normalCompletableFutureTest() throws ExecutionException, InterruptedException {

        CompletableFuture<String> normalCompletableFuture = CompletableFuture.supplyAsync(() -> {
            try {
                TimeUnit.SECONDS.sleep(5);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
            return "测试normalCompletableFutureTest";
        });
        System.out.println("get()方法,一直阻塞到出结果位置" + normalCompletableFuture.get());
        System.out.println("get(Long timeout, TimeUnit time)方法,设置阻塞时间,过期抛异常" + normalCompletableFuture.get(1, TimeUnit.SECONDS));
    }
返回结果:get()方法,一直阻塞到出结果位置测试normalCompletableFutureTest







2. 有返回值,当前任务正常完成以后,当前任务执行的结果会作为下一个任务的输入参数【thenApply】
    /**
     * 【有返回值】,默认使用ForkJoinPool.commonPool() 作为他的线程池执行异步代码
     */
    @Test
    public void thenApplyTest() throws ExecutionException, InterruptedException, TimeoutException {

        CompletableFuture<String> normalCompletableFuture = CompletableFuture.supplyAsync(() -> {
            try {
                TimeUnit.SECONDS.sleep(5);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
            return "测试normalCompletableFutureTest";
        });

        // 用上一次任务的返回值normalCompletableFuture 去调用thenApply方法,参数是element, element就是上一次任务的结果
        CompletableFuture<String> thenApplyFuture = normalCompletableFuture.thenApply((element) -> {

            System.out.println("入参:" + element);
            System.out.println("执行任务2...");
            return "这是第二个任务";
        });
        System.out.println("get()方法,一直阻塞到出结果位置" + thenApplyFuture.get());
    }
    返回结果:入参:测试normalCompletableFutureTest
              执行任务2...
              get()方法,一直阻塞到出结果位置:这是第二个任务






3. 无返回值,当前任务正常完成以后执行,当前任务的执行结果可以作为下一个任务的输入参数【thenAccept】
    /**
     * 【有返回值】,默认使用ForkJoinPool.commonPool() 作为他的线程池执行异步代码
     */
    @Test
    public void thenAcceptTest() throws ExecutionException, InterruptedException, TimeoutException {

        CompletableFuture<String> normalCompletableFuture = CompletableFuture.supplyAsync(() -> {
            try {
                TimeUnit.SECONDS.sleep(5);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
            return "测试normalCompletableFutureTest";
        });

        // 用上一次任务的返回值normalCompletableFuture 去调用thenApply方法,参数是element, element就是上一次任务的结果
        CompletableFuture<Void> thenAcceptFuture = normalCompletableFuture.thenAccept((element) -> {

            System.out.println("入参:" + element);
            System.out.println("执行任务2...");
        });
        // thenAcceptFuture.get() 返回结果会是 null, 因为无返回值
        System.out.println("get()方法,一直阻塞到出结果位置" + thenAcceptFuture.get());
    }
    返回结果:入参:测试normalCompletableFutureTest
              执行任务2...
              get()方法,一直阻塞到出结果位置:null
Logo

CSDN联合极客时间,共同打造面向开发者的精品内容学习社区,助力成长!

更多推荐