异步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());
一点点学习,一丝丝进步。不懈怠,才不会被时代淘汰