异步CompletableFuture线程

tips:解释下主线程等待,子线程执行,如果子线程发生异常会被捕捉,主线程也会发生异常而终止,不会一直阻塞下去

        ExecutorService executorService= Executors.newSingleThreadExecutor();
        Future<Double> cf = executorService.submit(()->{
            System.out.println(Thread.currentThread()+" start,time->"+System.currentTimeMillis());
            try {
                Thread.sleep(2000);
            } catch (InterruptedException e) {
            }


            if(false){//改成ture后就抛异常了,cf.get()也不会一直阻塞主线程
                throw new RuntimeException("test");
            }else{
                System.out.println(Thread.currentThread()+" exit,time->"+System.currentTimeMillis());
                return 1.2;
            }
        });
        System.out.println("run result->"+cf.get());

 

supplyAsync异步带有返回值

 

   CompletableFuture completableFuture= CompletableFuture.supplyAsync(()->{
            System.out.println(Thread.currentThread()+" start,time->"+System.currentTimeMillis());
            try {
                Thread.sleep(2000);
            } catch (InterruptedException e) {
            }
                System.out.println(Thread.currentThread()+" exit,time->"+System.currentTimeMillis());
                return "我是返回值";
            
        });
        System.out.println("completableFuture result->"+completableFuture.get());

 

runAsync异步没有返回值

 

        CompletableFuture cf = CompletableFuture.runAsync(()->{
            System.out.println(Thread.currentThread()+" start,time->"+System.currentTimeMillis());
            try {
                Thread.sleep(2000);
            } catch (InterruptedException e) {
            }
            if(false){
                throw new RuntimeException("test");
            }else{
                System.out.println(Thread.currentThread()+" exit,time->"+System.currentTimeMillis());
            }
        });
        System.out.println("main thread start,time->"+System.currentTimeMillis());
        //等待子任务执行完成
        System.out.println("run result->"+cf.get());

 

CompletableFuture里面执行的其实还是Executor的实现类,默认执行的是ForkJoinPool
源码如下:
   public static <U> CompletableFuture<U> supplyAsync(Supplier<U> supplier,
                                                       Executor executor) {
        return asyncSupplyStage(screenExecutor(executor), supplier);
    }

   static Executor screenExecutor(Executor e) {
        if (!useCommonPool && e == ForkJoinPool.commonPool())//这里是ForfJoinPool
            return asyncPool;
        if (e == null) throw new NullPointerException();
        return e;
    }

如果是机器是单核的,就会创建一个ThreadPerTaskExecutor的执行器:
源码如下:

    private static final boolean useCommonPool =
        (ForkJoinPool.getCommonPoolParallelism() > 1);//判断单核多核返回boolean值


    private static final Executor asyncPool = useCommonPool ?
        ForkJoinPool.commonPool()
 : new ThreadPerTaskExecutor();//单核就new一个执行器

ThreadPerTaskExecutor 实现Executor接口并且创建一个单线程
 static final class ThreadPerTaskExecutor implements Executor {
        public void execute(Runnable r) { new Thread(r).start(); }
    }

 

基于上述源码可以看到CompletableFuture应该有两个重载Executor的方法
于是乎有如下静态构造方法:
   public static <U> CompletableFuture<U> supplyAsync(Supplier<U> supplier,
                                                       Executor executor) {
        return asyncSupplyStage(screenExecutor(executor), supplier);
    }

         /111111111111111111111111111
        ForkJoinPool forkJoinPool=new ForkJoinPool();
         CompletableFuture completableFuture=CompletableFuture.supplyAsync(()->{
              //do yourself
                return xxxxx;
        
        },forkJoinPool);
     System.out.println("completableFuture result->"+completableFuture.get());


           /22222222222
        ExecutorService executorService= Executors.newSingleThreadExecutor();
        // 创建异步执行任务:
        CompletableFuture cf = CompletableFuture.runAsync(()->{
           //do yourself
        },executorService);
        System.out.println("main thread start,time->"+System.currentTimeMillis());
        //等待子任务执行完成
        System.out.println("run result->"+cf.get());

 

异步回调
1、thenApply:表示某个任务执行完成后执行的动作,即回调方法,会将该任务的执行结果即方法返回值作为入参传递到回调方法中
2.thenApplyAsync

 

      ForkJoinPool pool=new ForkJoinPool();
        // 创建异步执行任务:
        CompletableFuture cf = CompletableFuture.supplyAsync(()->{
            System.out.println(Thread.currentThread()+" 任务一,开始time->"+System.currentTimeMillis());
            try {
                Thread.sleep(2000);
            } catch (InterruptedException e) {
            }
            System.out.println(Thread.currentThread()+" 任务一,结束time->"+System.currentTimeMillis());

            return "123456789";
        },pool);
        Object o = cf.get();
        System.out.println(o);

        CompletableFuture completableFuture = cf.thenApplyAsync((result)->{
            System.out.println(Thread.currentThread()+" 任务二,开始time->"+System.currentTimeMillis());
            try {
                Thread.sleep(2000);
            } catch (InterruptedException e) {
            }
            System.out.println(Thread.currentThread()+" 任务二,结束time->"+System.currentTimeMillis());
            return "456789123"+result;
        });
        System.out.println("main thread start cf.get(),time->"+System.currentTimeMillis());
        System.out.println(completableFuture.get());
        pool.shutdown();

 

thenAccept:接收上一个任务的执行结果作为入参,但是没有返回值
thenRun:没入参也没返回值

 

        ForkJoinPool pool=new ForkJoinPool();
        // 创建异步执行任务:
        CompletableFuture cf = CompletableFuture.supplyAsync(()->{
            try {
                Thread.sleep(2000);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
            return "123";
        },pool);

        CompletableFuture completableFuture = cf.thenApply((result)->{
            try {
                Thread.sleep(2000);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
            return "456";
        }).thenAccept((result)->{//接收上一个任务的执行结果作为入参,但是没有返回值
            try {
                Thread.sleep(2000);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
            System.out.println("接收:"+result);
        }).thenRun(()->{//没入参也没返回值
            try {
                Thread.sleep(2000);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
            System.out.println("啥也不干");
        });
        System.out.println(":::::::"+cf.get());
        System.out.println("等待最后一个thenRun执行完成completableFuture才输出:"+completableFuture.get());

 

 

  exceptionally方法指定某个任务执行异常时执行的回调方法,
会将抛出异常作为参数传递到回调方法中,
如果该任务正常执行,exceptionally
方法返回的CompletionStage的result就是该任务正常执行的结果( CompletableFuture<T> implements Future<T>, CompletionStage<T>)

 

        ForkJoinPool pool=new ForkJoinPool();
        // 创建异步执行任务:
        CompletableFuture<Double> cf = CompletableFuture.supplyAsync(()->{
            System.out.println("任务一");
            if(true){
                throw new RuntimeException("test");
            }else{
                return 1.23;
            }
        },pool);
        //cf执行异常时,将抛出的异常作为入参传递给回调方法
        CompletableFuture<Double> cf2= cf.exceptionally((param)->{
            System.out.println("任务二");
            System.out.println("error stack trace->");
            param.printStackTrace();
            System.out.println(Thread.currentThread()+" exit,time->"+System.currentTimeMillis());
            return -1.0;
        });
        //cf正常执行时执行的逻辑,如果执行异常则不调用此逻辑
        CompletableFuture cf3=cf.thenAccept((param)->{
            System.out.println("任务三");
            System.out.println("param->"+param);
        });
        //等待子任务执行完成,此处无论是任务二和任务三都可以实现job2退出,主线程才退出
        // 如果是cf,则主线程不会等待任务二执行完成自动退出了
        //cf2.get时,没有异常,但是依然有返回值,就是cf的返回值
        System.out.println("》》》》》》》》》》->"+cf2.get());

 

posted @ 2022-04-11 16:01  余生请多指教ANT  阅读(54)  评论(0编辑  收藏  举报