CompletableFuture>java8新增异步工具使用方法

本文详细介绍了Java并发库CompletableFuture的使用,包括无返回值、有返回值、异常处理、线程串行化、任务组合等多种异步任务场景,展示了如何通过Future实现线程池的高效管理和任务间的协调。同时,文中还提到了手动创建线程池的重要性。
摘要由CSDN通过智能技术生成

目录

1.无返回的异步任务

2.有返回值的异步任务

3.有返回值+异常信息的异步任务

4.线程串行化,能接收上一步结果,但是无返回值

5. 线程串行化,能接收上一步结果,并且有返回值

6.两任务组合服务,两个都完成才往下执行

7.两任务组合服务,完成其中一个

8.多组合,等待所有方法都执行完,才往下执行

9.多组合,其中只要有一个方法执行完成边可往下执行


注意!!!:强烈建议手动创建线程池,这里为了方便演示所以直接Java提供的线程池

若想学习手动创建线程池欢迎观看我的另一篇博客《手动创建线程池》

1.无返回的异步任务

1.1.runAsync();

    //警告:强烈建议手动创建线程池,这里为了方便演示所以直接Java提供的线程池
    //若想学习手动创建线程池欢迎观看我的另一篇博客《手动创建线程池》
    public static ExecutorService executor = Executors.newFixedThreadPool(10);

    @Test
    public void demo(){
      //无返回值异步任务
        CompletableFuture.runAsync(() -> {
            System.out.println("当前线程: " + Thread.currentThread().getId());
            int t = 10 / 2;
            System.out.println("运行结果: " + t);
        }, executor);
    }

控制台输出:

当前线程: 33
运行结果: 5

2.有返回值的异步任务

2.2.supplyAsync();

    @Test
    public void demo() throws ExecutionException, InterruptedException {
        CompletableFuture<Integer> future = CompletableFuture.supplyAsync(() -> {
            System.out.println("当前线程: " + Thread.currentThread().getId());
            int t = 10 / 2;
            System.out.println("运行结果: " + t);
            return t;
        }, executor);
        Integer integer = future.get();
        System.out.println("返回值为: " + integer);
    }

控制台输出:

当前线程: 33
运行结果: 5
返回值为: 5

3.有返回值+异常信息的异步任务

3.1.whenComplete():虽然能得到异常信息,但是没法修改返回的数据;(此文章只演示该方法)

3.2.exceptionally():可以感知异常,同时返回默认值;

@Test
public void demo() throws ExecutionException, InterruptedException {
    CompletableFuture<Integer> future = CompletableFuture.supplyAsync(() -> {
        System.out.println("当前线程: " + Thread.currentThread().getId());
        int t = 10 / 0;//故意弄了一个BUG
        System.out.println("运行结果: " + t);
        return t;
    }, executor).whenComplete((res, err) -> {
        //虽然能得到异常信息,但是没法修改返回的数据
        System.out.println("异步任务成功完成了..结果是: " + res + ";异常是:" + err);
    }).exceptionally(throwable -> {
        //可以感知异常,同时返回默认值;
        return 6666;
    });
    Integer integer = future.get();
    System.out.println("返回的结果: " + integer);
}

控制台输出:

当前线程: 33
异步任务成功完成了..结果是: null;异常是:java.util.concurrent.CompletionException: java.lang.ArithmeticException: / by zero
返回的结果: 6666

4.线程串行化,能接收上一步结果,但是无返回值

4.1.thenAcceptAsync();

    @Test
    public void demo() throws ExecutionException, InterruptedException {
        CompletableFuture<Void> future = CompletableFuture.supplyAsync(() -> {
            System.out.println("当前线程: " + Thread.currentThread().getId());
            int t = 10 / 2;
            System.out.println("运行结果: " + t);
            return t;
        }, executor).thenAcceptAsync(res -> {
            System.out.println("任务2启动,接收到上一步的结果是:" + res);
        }, executor);
    }

控制台输出:

当前线程: 33
运行结果: 5
任务2启动,接收到上一步的结果是:5

5. 线程串行化,能接收上一步结果,并且有返回值

5.1.thenApplyAsync();

  @Test
    public void demo() throws ExecutionException, InterruptedException {
        CompletableFuture<String> future = CompletableFuture.supplyAsync(() -> {
            System.out.println("当前线程: " + Thread.currentThread().getId());
            int t = 10 / 2;
            System.out.println("运行结果: " + t);
            return t;
        }, executor).thenApplyAsync(res -> {
            System.out.println("任务2启动...接收到上一步的结果:" + res);
            return "Hello: " + res;
        }, executor);
        System.out.println("返回的东西是: " + future.get());
    }

控制台输出:

当前线程: 33
运行结果: 5
任务2启动...接收到上一步的结果:5
返回的东西是: Hello: 5

6.两任务组合服务,两个都完成才往下执行

6.1.runAfterBothAsync(): 组合但是没有返回值;
6.2.thenAcceptBothAsync: 组合有返回值;
6.3.thenCombineAsync: 组合有返回值,并且可以更改数据;(此文章只演示该方法)

 @Test
    public void demo() throws ExecutionException, InterruptedException {
        //第一个任务
        CompletableFuture<Integer> future1 = CompletableFuture.supplyAsync(() -> {
            System.out.println("当前线程1: " + Thread.currentThread().getId());
            int t = 10 / 2;
            System.out.println("运行结果1: " + t);
            return t;
        }, executor);
        //第二个任务
        CompletableFuture<String> future2 = CompletableFuture.supplyAsync(() -> {
            System.out.println("当前线程2: " + Thread.currentThread().getId());
            System.out.println("运行结果2: ");
            return "Hello";
        }, executor);
        /*
         *组合
         * .runAfterBothAsync(): 组合但是没有返回值
         * .thenAcceptBothAsync: 组合有返回值
         * .thenCombineAsync: 组合有返回值,并且可以更改数据
         */
        CompletableFuture<String> future = future1.thenCombineAsync(future2, (f1, f2) -> {
            return "组合技:" + f1 + f2;
        }, executor);

        System.out.println("最后组合返回的参数:" + future.get());
    }

控制台输出:

当前线程1: 33
运行结果1: 5
当前线程2: 34
运行结果2:
最后组合返回的参数:组合技:5Hello

7.两任务组合服务,完成其中一个

7.1.runAfterEitherAsync: 不感知结果,自己没有返回值;

7.2.acceptEitherAsync: 感知结果,自己没有返回值.注:两个任务的返回值类型必须一致;

7.3.applyToEitherAsync:感知结果,有返回值;(此文章只演示该方法)

    @Test
    public void demo() throws ExecutionException, InterruptedException {
        //第一个任务
        CompletableFuture<Object> future1 = CompletableFuture.supplyAsync(() -> {
            System.out.println("当前线程1: " + Thread.currentThread().getId());
            int t = 10 / 2;
            try {
                Thread.sleep(3000);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
            System.out.println("运行结果1: " + t);
            return t;
        }, executor);
        //第二个任务
        CompletableFuture<Object> future2 = CompletableFuture.supplyAsync(() -> {
            System.out.println("当前线程2: " + Thread.currentThread().getId());
            System.out.println("运行结果2: ");
            return "Hello";
        }, executor);

        /*
         *.runAfterEitherAsync: 不感知结果,自己没有返回值
         * .acceptEitherAsync: 感知结果,自己没有返回值.注:两个任务的返回值类型必须一致
         *
         */
        CompletableFuture<String> future = future1.applyToEitherAsync(future2, (res) -> {
            return res.toString() + "添加自己的特色";
        }, executor);

        System.out.println(future.get());
    }

控制台输出:

当前线程1: 33
当前线程2: 34
运行结果2:
Hello添加自己的特色

8.多组合,等待所有方法都执行完,才往下执行

8.1.allOf();

    @Test
    public void demo() throws ExecutionException, InterruptedException {
        Map<String, String> map = new HashMap<>();
        //第一个任务
        CompletableFuture<String> futureImg = CompletableFuture.supplyAsync(() -> {
            System.out.println("查询商品的图片信息");
            map.put("照片信息", "lisa.jpg");
            return "lisa.jpg";
        }, executor);

        //第二个任务
        CompletableFuture<String> futureAttr = CompletableFuture.supplyAsync(() -> {
            System.out.println("查询商品的属性");
            map.put("商品的属性", "黑色+256G");
            return "黑色+256G";
        }, executor);

        //第三个任务
        CompletableFuture<String> futureDesc = CompletableFuture.supplyAsync(() -> {
            System.out.println("查询商品介绍");
            map.put("商品介绍", "华为");
            return "华为";
        }, executor);

        CompletableFuture<Void> allOf = CompletableFuture.allOf(futureImg, futureAttr, futureDesc);
        allOf.get();//虽然没办法获取数据,但是需要他阻塞main方法的线程,防止异步线程还没执行完,main方法就先结束了
        String result = futureImg.get() + futureAttr.get() + futureDesc.get();
        System.out.println("获取到的返回值数据为:"+result);
        System.out.println("map收集到的数据为:"+map.toString());
    }

 控制台输出:

查询商品的图片信息
查询商品的属性
查询商品介绍
获取到的返回值数据为:lisa.jpg黑色+256G华为
map收集到的数据为:{商品的属性=黑色+256G, 商品介绍=华为, 照片信息=lisa.jpg}

9.多组合,其中只要有一个方法执行完成边可往下执行

9.1.anyOf();

 @Test
    public void demo() throws ExecutionException, InterruptedException {
        Map<String, String> map = new HashMap<>();
        //第一个任务
        CompletableFuture<String> futureImg = CompletableFuture.supplyAsync(() -> {
            System.out.println("查询商品的图片信息");
            map.put("照片信息", "lisa.jpg");
            return "lisa.jpg";
        }, executor);

        //第二个任务
        CompletableFuture<String> futureAttr = CompletableFuture.supplyAsync(() -> {
            System.out.println("查询商品的属性");
            map.put("商品的属性", "黑色+256G");
            return "黑色+256G";
        }, executor);

        //第三个任务
        CompletableFuture<String> futureDesc = CompletableFuture.supplyAsync(() -> {
            System.out.println("查询商品介绍");
            map.put("商品介绍", "华为");
            return "华为";
        }, executor);

        CompletableFuture<Object> anyOf = CompletableFuture.anyOf(futureImg, futureAttr, futureDesc);
        Object result = anyOf.get();
        System.out.println("获取到的返回值数据为:"+result);
        System.out.println("map收集到的数据为:"+map.toString());
    }

控制台输出:

查询商品的图片信息
查询商品的属性
获取到的返回值数据为:lisa.jpg
map收集到的数据为:{商品的属性=黑色+256G, 照片信息=lisa.jpg}
查询商品介绍

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值