CompletableFuture 简单使用

164 阅读2分钟

「这是我参与11月更文挑战的第21天,活动详情查看:2021最后一次更文挑战

CompletableFuture

通过前面的两个future 的demo,我们发现了个问题,我们无法知道任务什么时候完成.

要么通过get的阻塞等待,或者isDone自旋判断是否完成,这两个都不是完整版的future.

jdk8 新增了CompletableFuture类.

其中,可以分成这么几类

💡 连续关系

即连续执行.使用then 前缀.

image.png

💡 与关系

条件同时满足,包含combine或者both

image.png

💡 或关系

其一满足即可,包含Either

image.png

demo

1.可以直接通过runAsync方法异步执行Runable内容,类似new Thread(new Runable()),没有返回值

			// 异步执行runable,没有返回结果
        CompletableFuture<Void> future = CompletableFuture.runAsync(() -> {
            System.out.println("家里电脑开始下载游戏"+LocalTime.now());
            try {
                Thread.sleep(4000);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
            System.out.println("4小时下载完成 : " + LocalTime.now());
        });

2.通过supplyAsync方法异步执行Callable内容,有返回值

// supplyAsync 有返回值
        CompletableFuture<String> integerCompletableFuture = CompletableFuture.supplyAsync(() -> {
            System.out.println("家里电脑开始下载游戏" + LocalTime.now());
            try {
                Thread.sleep(4000);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
//            System.out.println("4小时下载完成 : " + LocalTime.now());
            return ("4小时下载完成 : " + LocalTime.now());
        });

				System.out.println(integerCompletableFuture.get());

3..使用链式编程,在异步执行后面跟上.thenApply(Function) 即可在任务1完成立即执行任务2,并传递任务1返回的参数.

thenApply有返回结果

注意:这两个任务不一定使用的同一个线程.

		CompletableFuture<Integer> integerCompletableFuture1 = CompletableFuture.supplyAsync(() -> {
            int hour = LocalTime.now().getHour();
            System.out.println("future1返回当前的小时为 : " + hour);
            return hour;
        })
                // 通过thenApply可以获取前一个future返回的结果
                .thenApply(t -> {
            System.out.println("future2接收的当前小时为 : " + t);
            return t + 2;
        });

image.png

4.thenAccept 接收参数,不用返回结果

CompletableFuture<Void> integerCompletableFuture1 = CompletableFuture.supplyAsync(() -> {
            int hour = LocalTime.now().getHour();
            System.out.println("future1返回当前的小时为 : " + hour);
            return hour;
        })
                // 通过thenApply可以获取前一个future返回的结果,有返回结果
                .thenAccept(t -> {
            System.out.println("future2接收的当前小时为 : " + t);
        });

5.thenRun 不接受参数,不返回结果

		CompletableFuture<Void> integerCompletableFuture1 = CompletableFuture.supplyAsync(() -> {
            int hour = LocalTime.now().getHour();
            System.out.println("future1返回当前的小时为 : " + hour);
            return hour;
        })
                // 通过thenApply可以获取前一个future返回的结果,有返回结果
                .thenAccept(t -> {
            System.out.println("future2接收的当前小时为 : " + t);
        }).thenRun(()->{
                    System.out.println("future3完成的当前时间" + LocalTime.now());
                });

6.thenCombine 处理两个独立的CompletableFuture结果

				final int size = 10;
        final int level = 2;

        CompletableFuture<Integer> integerCompletableFuture3 = CompletableFuture.supplyAsync(() -> {
            //计算面积
            int area = size * 10;
            return area;
        });

        CompletableFuture<Integer> integerCompletableFuture2 = CompletableFuture.supplyAsync(() -> {
            // 计算价格
            int price = (int) (level * 2);
            return price;
        });

        // thenCombine 聚合两个独立的completableFuture
        CompletableFuture<Double> doubleCompletableFuture = integerCompletableFuture3.thenCombine(integerCompletableFuture2, (t1, t2) -> {
            System.out.println("价格为 : " + t2);
            System.out.println("面积为 : " + t1);
            double total = t1 * t2;
            System.out.println("总价为 : " + total);
            return total;
        });

        System.out.println(doubleCompletableFuture.get());

image.png

7.allOf 等待所有任务结束

					// allOf 等待所有任务结束
        CompletableFuture<Void> future1 = CompletableFuture.allOf(integerCompletableFuture3, integerCompletableFuture2);
        System.out.println(future1.get());