线程池与CompletableFuture 异步编排

使用线程池的好处:
1、降低资源的消耗
通过重复利用已经创建好的线程降低线程的创建和销毁带来的损耗
2、提高响应速度
因为线程池中的线程数没有超过线程池的最大上限时,有的线程处于等待分配任务
的状态,当任务来时无需创建新的线程就能执行
3、提高线程的可管理性
线程池会根据当前系统特点对池内的线程进行优化处理,减少创建和销毁线程带来
的系统开销。无限的创建和销毁线程不仅消耗系统资源,还降低系统的稳定性,使
用线程池进行统一分配

以下代码首先创建线程池executor ,将其传入异步编排对象CompletableFuture,它提供了四个静态方法来创建一个异步操作。

1、创建异步对象方法

线程池与CompletableFuture 异步编排_第1张图片

1、runXxxx 都是没有返回结果的,supplyXxx 都是可以获取返回结果的
2、可以传入自定义的线程池,否则就用默认的线程池
public class Thread1Test {

    public static ExecutorService executor = Executors.newFixedThreadPool(10);

    public static void main(String[] args) throws ExecutionException, InterruptedException {
        System.out.println("方法开始。。。");

        CompletableFuture<Void> future = CompletableFuture.runAsync(() -> {
            System.out.println("当前线程" + Thread.currentThread().getId());
            int i = 10 / 2;
            System.out.println(i);
        }, executor);
        System.out.println("方法结束");

    }
}

线程池与CompletableFuture 异步编排_第2张图片

2、计算完成时回调方法

使用supplyAsync可以获得线程运行返回结果:

CompletableFuture<Integer> future = CompletableFuture.supplyAsync(() -> {
            System.out.println("当前线程" + Thread.currentThread().getId());
            int i = 10 / 2;
            System.out.println("运行结果"+i);
            return i;
        }, executor);
        Integer integer = future.get();

提供了计算完成时回调方法,在处理完成后,对结果进行操作:
线程池与CompletableFuture 异步编排_第3张图片
whenComplete 可以处理正常和异常的计算结果,exceptionally 处理异常情况。
whenComplete 和 whenCompleteAsync 的区别:
whenComplete:是执行当前任务的线程执行继续执行 whenComplete 的任务。
whenCompleteAsync:是执行把 whenCompleteAsync 这个任务继续提交给线程池
来进行执行。
方法不以 Async 结尾,意味着 Action 使用相同的线程执行,而 Async 可能会使用其他线程
执行(如果是使用相同的线程池,也可能会被同一个线程选中执行)
whenComplete可以得到任务完成结果,参数1是结果,参数2是异常:

CompletableFuture<Integer> future = CompletableFuture.supplyAsync(() -> {
            System.out.println("当前线程" + Thread.currentThread().getId());
            int i = 10 / 0;
            System.out.println("运行结果"+i);
            return i;
        }, executor).whenComplete((res,excption)->{
            System.out.println("异步完成,结果是"+res+"异常是:"+excption);
        });

这里制造除数为0的异常:
线程池与CompletableFuture 异步编排_第4张图片
exceptionally虽然能得到异常信息,但是没法修改返回数据,感知异常,返回默认值

 CompletableFuture<Integer> future = CompletableFuture.supplyAsync(() -> {
            System.out.println("当前线程" + Thread.currentThread().getId());
            int i = 10 / 0;
            System.out.println("运行结果"+i);
            return i;
        }, executor).whenComplete((res,excption)->{
            System.out.println("异步完成,结果是"+res+"异常是:"+excption);
        }).exceptionally(throwable -> {
            //感知异常,返回默认值
            return 10;
        });
        Integer integer = future.get();

线程池与CompletableFuture 异步编排_第5张图片

3、handle方法

线程池与CompletableFuture 异步编排_第6张图片
handle和 complete 一样,可对结果做最后的处理(可处理异常),可改变返回值。

CompletableFuture<Integer> future = CompletableFuture.supplyAsync(() -> {
            System.out.println("当前线程" + Thread.currentThread().getId());
            int i = 10 / 4;
            System.out.println(i);
            return i;
        }, executor).handle((res,thr)->{
            if (res!=null){
                return res *2;
            }
            if (thr!=null){
                return 0;
            }
            return 1;
        });

线程池与CompletableFuture 异步编排_第7张图片

4、线程串行化方法

线程池与CompletableFuture 异步编排_第8张图片
thenApply 方法:当一个线程依赖另一个线程时,获取上一个任务返回的结果,并返回当前
任务的返回值。
thenAccept 方法:消费处理结果。接收任务的处理结果,并消费处理,无返回结果。
thenRun 方法:只要上面的任务执行完成,就开始执行 thenRun,只是处理完任务后,执行
thenRun 的后续操作
带有 Async 是多开一个线程,是异步执行的。同之前。
以上都要前置任务成功完成。

      //线程串行化
        /* 1、 thenRunAsync 不能获取上一步的执行结果
           2、 thenAcceptAsync 能接受上一步结果,但无返回值
           3、 thenApplyAsync能接受上一步结果,有返回值
        * */
 CompletableFuture<String> future = CompletableFuture.supplyAsync(() -> {
            System.out.println("当前线程" + Thread.currentThread().getId());
            int i = 10 / 4;
            System.out.println("运行结果"+i);
            return i;
        }, executor).thenApplyAsync(res -> {
            System.out.println("任务2启动了" + res);

            return "hello" + res;
        }, executor);

线程池与CompletableFuture 异步编排_第9张图片

5、两任务组合 - 都要完成

线程池与CompletableFuture 异步编排_第10张图片
两个任务必须都完成,触发该任务。

runAfterBoth:组合两个 future,不需要获取 future 的结果,只需两个 future 处理完任务后,
处理该任务。

CompletableFuture<Integer> future01 = CompletableFuture.supplyAsync(() -> {
            System.out.println("任务1线程" + Thread.currentThread().getId());
            int i = 10 / 4;
            System.out.println("任务1线程结束"+i);
            return i;
        }, executor);

        CompletableFuture<String> future02 = CompletableFuture.supplyAsync(() -> {
            System.out.println("任务2线程" + Thread.currentThread().getId());

            System.out.println("任务2线程结束");
            return "hello";
        }, executor);
        future01.runAfterBothAsync(future02,()->{
            System.out.println("任务3开始");
        },executor);

        System.out.println("方法结束");

线程池与CompletableFuture 异步编排_第11张图片
thenAcceptBoth:组合两个 future,获取两个 future 任务的返回结果,然后处理任务,没有
返回值。

future01.thenAcceptBothAsync(future02,(f1,f2)->{
           System.out.println("任务3开始...之前的结果"+f1+f2);
       },executor);

线程池与CompletableFuture 异步编排_第12张图片

thenCombine:组合两个 future,获取两个 future 的返回结果,并返回当前任务的返回值

 CompletableFuture<String> future = future01.thenCombineAsync(future02, (f1, f2) -> {
            return "组合处理任务1、2的结果" + f1 + f2 + "999";
        }, executor);

线程池与CompletableFuture 异步编排_第13张图片

6、两任务组合 - 一个完成

线程池与CompletableFuture 异步编排_第14张图片

runAfterEither:两个任务有一个执行完成,不需要获取 future 的结果,处理任务,也没有返
回值。

 future01.runAfterEitherAsync(future02,()->{
           System.out.println("任务3开始前的结果");
       },executor);

线程池与CompletableFuture 异步编排_第15张图片
acceptEither:两个任务有一个执行完成,获取它的返回值,处理任务,没有新的返回值。

future01.acceptEitherAsync(future02,(res)->{
            System.out.println("任务3开始前的结果"+res);
        },executor);

线程池与CompletableFuture 异步编排_第16张图片
applyToEither:两个任务有一个执行完成,获取它的返回值,处理任务并有新的返回值。

CompletableFuture<String> eitherAsync = future01.applyToEitherAsync(future02, (res) -> {
            System.out.println("任务3开始前结果" + res);
            return res.toString() + "--->" + "ke";
        }, executor);

        System.out.println("方法结束"+eitherAsync.get());

线程池与CompletableFuture 异步编排_第17张图片

7、多任务组合

在这里插入图片描述

allOf:等待所有任务完成

  CompletableFuture<String> img = CompletableFuture.supplyAsync(() -> {
            System.out.println("查询商品信息");
            return "hello.jpg";
        },executor);
        CompletableFuture<String> attr = CompletableFuture.supplyAsync(() -> {
            System.out.println("查询属性信息");
            return "黑丝";
        },executor);
        CompletableFuture<String> desc = CompletableFuture.supplyAsync(() -> {
            try {
                Thread.sleep(3000);
                System.out.println("查询商品介绍");

            } catch (InterruptedException e) {
                e.printStackTrace();
            }
            return "油量";
        },executor);
        CompletableFuture<Void> allOf = CompletableFuture.allOf(img, attr, desc);
        allOf.get();
        System.out.println("任务结束"+img.get()+attr.get()+desc.get());

线程池与CompletableFuture 异步编排_第18张图片
anyOf:只要有一个任务完成

 CompletableFuture<Object> anyOf = CompletableFuture.anyOf(img, attr, desc);

线程池与CompletableFuture 异步编排_第19张图片

你可能感兴趣的:(谷粒,springboot,IT,java,数据库)