Java CompletableFuture 用法

CompletableFuture 是 java 8新增的,主要用来异步编程,使用时有一些需要注意到地方,下面的代码中已经备注

import java.util.List;
import java.util.Random;
import java.util.concurrent.*;
import java.util.stream.Collectors;
import java.util.stream.IntStream;

public class FutureDemo {
    private static final int MAX_THREADS = 400;

    private final Random random = new Random();
    private final Executor executor;
    private final int taskCount;

    FutureDemo(int taskCount) {
        this.taskCount = taskCount;
        executor = Executors.newFixedThreadPool(Math.min(taskCount, MAX_THREADS), r -> {
            Thread thread = new Thread(r);
            thread.setDaemon(true);
            return thread;
        });
    }

    private void delay(int ms) {
        try {
            Thread.sleep(ms);
        } catch (InterruptedException e) {
            throw new RuntimeException(e);
        }
    }

    private double task1(int a) {
        delay(100);
        return Math.pow(a, 2);
    }

    private int task2(double a) {
//        delay();
        return (int) Math.sqrt(a);
    }

    private char task3(int i) {
        int ms = 10 + random.nextInt(90);
        delay(ms);
        return (char) (i - 1 + 'A');
    }

    private void testCase1() {
        measure("testCase1()", () -> {
            List<CompletableFuture<Double>> futureList = IntStream.rangeClosed(1, taskCount)
                    .mapToObj(i -> CompletableFuture.supplyAsync(() -> task1(i), executor))
                    .collect(Collectors.toList());
            List<Double> results = futureList.stream()
                    .map(CompletableFuture::join).//等待所有异步操作完成
                            collect(Collectors.toList());
            System.out.println(results);
        });
    }

    // Stream 结合 CompletableFuture 实现流水线式的异步任务
    private void testCase2() {
        measure("testCase2()", () -> {
            /*todo 知识点
             * thenCompose 后面的任务需要以前面的任务的输出作为输入
             * thenCombine 组合两个独立的任务,合并两个任务的输出
             * orTimeout 指定任务的超时时间,超时后会抛出 TimeoutException
             * completeOnTimeout 指定任务的超时时间,超时后用指定的默认值作为输出
             * */
            List<CompletableFuture<Character>> futureList = IntStream.rangeClosed(1, taskCount)
                    .mapToObj(i -> CompletableFuture.supplyAsync(() -> task1(i), executor))
                    .map(future -> future.thenApply(this::task2))// task2 不怎么耗时,采用同步操作
//                    .map(future -> future.thenCompose(i -> CompletableFuture.supplyAsync(() -> task3(i), executor)))
                    .map(future -> future.thenApplyAsync(this::task3, executor)
                            //.orTimeout(300, TimeUnit.MILLISECONDS)
                            .completeOnTimeout('*', 220, TimeUnit.MILLISECONDS)
                    )
                    .collect(Collectors.toList());

            /*List<Character> results = futureList.stream()
                    .map(CompletableFuture::join).//等待所有异步操作完成
                            collect(Collectors.toList());
            System.out.println(results);*/

            /*todo 知识点
             * thenAccept 每个任务完成时触发,有的时候不需要等所有任务都完成才执行某些操作(如分页加载,进度更新等)
             * 如果需要监听所有任务都已完成,可以使用 CompletableFuture.allOf(futures).join()
             * 有些时候只要有一个任务完成即可满足需求,可以使用 CompletableFuture.anyOf(futures)
             * 注:创建 futures 只是创建了一组待执行的任务,真正触发任务执行的是 join 方法
             * */
            long start = System.currentTimeMillis();
            CompletableFuture[] futures = futureList.stream()
                    .map(future -> future.thenAccept(character -> {
                        long time = System.currentTimeMillis() - start;
                        System.out.println("单个任务完成:" + character + ",耗时:" + time + "ms");
                    }))
                    .toArray(CompletableFuture[]::new);

            CompletableFuture.allOf(futures).join();//等待所有异步操作完成

            //如果 future 添加了 thenAccept 监听,返回的结果将是null
//            Object o = CompletableFuture.anyOf(futures).join();
//            System.out.println(o);
        });
    }

    public static void measure(String s, Runnable r) {
        long start = System.currentTimeMillis();
        r.run();
        long end = System.currentTimeMillis();
        System.out.println(s + " 用时 " + (end - start) + " ms");
    }

    public static void main(String[] args) {
        System.out.println("availableProcessors: " + Runtime.getRuntime().availableProcessors());

        final int taskCount = 26;
        FutureDemo futureDemo = new FutureDemo(taskCount);
//        futureDemo.testCase1();
        futureDemo.testCase2();
    }
}

  • 0
    点赞
  • 5
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值