CompletableFuture创建异步任务的三种方法:
completedFuture-用于构建一个现成的CompletableFuture对象,
runAsync-没有返回值,
supplyAsync-支持返回值
获取CompletableFuture结果的方法有两个:join(),get().二者的区别在于join方法抛出的是RuntimeException,不需要显式进行处理,而使用get就需要显式捕获异常。
get可以设定超时时间,getNow可以设定默认值,当未获取到future值或者出现异常时,则返回设定的默认值
注意:get,join方法是获取线程的结果,不是让线程执行,所以即使不加get,join方法线程也会执行
//使用自定义线程池 ExecutorService executor = Executors.newCachedThreadPool(); //runAsync的使用,如果不指定自定义线程池就用默认的ForkJoinPool.commonPool线程池 CompletableFuture<String> future1 = CompletableFuture.completedFuture("hello world"); CompletableFuture<Void> runFuture = CompletableFuture.runAsync(() -> System.out.println("runAsync执行语句"), executor); //supplyAsync的使用 CompletableFuture<String> supplyFuture = CompletableFuture.supplyAsync(() -> { System.out.println("supplyAsync执行语句"); return "supplyAsync返回语句"; }, executor); //runAsync的future没有返回值,输出null System.out.println(runFuture.join()); //supplyAsync的future,有返回值 System.out.println(supplyFuture.join()); try { future1.get(1000, TimeUnit.MILLISECONDS);//需要处理异常,可以设置超时时间 } catch (InterruptedException e) { throw new RuntimeException(e); } catch (ExecutionException e) { throw new RuntimeException(e); } catch (TimeoutException e) { throw new RuntimeException(e); } /* future1.join();//无需处理异常 future1.getNow("默认值");//可以设置默认值*/ executor.shutdown(); // 线程池需要关闭CompletableFuture的简单异步回调方法 1:不关心上一个任务的执行返回结果,无传参,无返回值-thenRun/thenRunAsync
thenRun和thenRunAsync的区别:如果执行第一个任务的时候,传入了一个自定义线程池,调用thenRun方法执行第二个任务时,则第二个任务和第一个任务是共用同一个线程池,调用thenRunAsync执行第二个任务时,则第一个任务使用的是自己传入的线程池,第二个任务使用的是ForkJoin线程池.
后面的thenAccept和thenAcceptAsync,thenApply和thenApplyAsync等,它们之间的区别也是这个
CompletableFuture<String> orgFuture = CompletableFuture.supplyAsync( () -> { System.out.println("先执行第一个CompletableFuture方法任务"); return "任务一执行完成"; } ); CompletableFuture thenRunFuture = orgFuture.thenRun(() -> { System.out.println("接着执行第二个任务"); }); System.out.println(thenRunFuture.get());CompletableFuture的简单异步回调方法 2:thenAccept/thenAcceptAsync
CompletableFuture的thenAccept方法表示,第一个任务执行完成后,执行第二个任务,会将任务一的执行结果作为入参,传递到任务二方法中,但是任务二是没有返回值的。
CompletableFuture<String> orgFuture = CompletableFuture.supplyAsync( () -> { System.out.println("CompletableFuture任务一"); return "任务一返回值"; } ); CompletableFuture thenAcceptFuture = orgFuture.thenAccept((a) -> { if ("任务一返回值".equals(a)) { System.out.println("一致"); } else { System.out.println("不一致"); } }); System.out.println(thenAcceptFuture.get());CompletableFuture的简单异步回调方法: 3.thenApply/thenApplyAsync
CompletableFuture的thenApply方法表示,第一个任务执行完成后,执行第二个任务,会将任务一的执行结果作为入参,传递到任务二方法中,任务二有返回值。
CompletableFuture<String> orgFuture = CompletableFuture.supplyAsync( () -> { System.out.println("CompletableFuture任务一"); return "任务一返回值"; } ); CompletableFuture<String> thenAcceptFuture = orgFuture.thenApply((a) -> { if ("任务一返回值".equals(a)) { System.out.println("一致"); } else { System.out.println("不一致"); } return "任务二返回值"; }); System.out.println(thenAcceptFuture.get());CompletableFuture的简单异步回调方法: 4.exceptionally
CompletableFuture的exceptionally方法表示,某个任务执行异常时,执行的回调方法;并且有抛出异常作为参数,传递到回调方法。
CompletableFuture<String> orgFuture = CompletableFuture.supplyAsync( () -> { System.out.println("CompletableFuture任务一"); return "任务一返回值"; } ); CompletableFuture<String> thenAcceptFuture = orgFuture.thenApply((a) -> { if ("任务一返回值".equals(a)) { System.out.println("一致"); } else { System.out.println("不一致"); } throw new RuntimeException(); }); CompletableFuture<String> exceptionFuture = thenAcceptFuture.exceptionally((e) -> { e.printStackTrace(); return "你的程序异常啦"; }); System.out.println(exceptionFuture.get());CompletableFuture的简单异步回调方法: 5.whenComplete
CompletableFuture的whenComplete方法表示,某个任务执行完成后,执行的回调方法,无返回值;并且whenComplete方法返回的CompletableFuture的result是上个任务的结果。
CompletableFuture<String> orgFuture = CompletableFuture.supplyAsync( () -> { System.out.println("当前线程名称:" + Thread.currentThread().getName()); try { Thread.sleep(2000L); } catch (InterruptedException e) { e.printStackTrace(); } return "任务一返回结果"; } ); CompletableFuture<String> rstFuture = orgFuture.whenComplete((a, throwable) -> { System.out.println("当前线程名称:" + Thread.currentThread().getName()); System.out.println("上个任务执行完啦,还把" + a + "传过来"); if ("任务一返回结果".equals(a)) { System.out.println("一致"); } }); System.out.println(rstFuture.get());CompletableFuture的简单异步回调方法: 6.handle CompletableFuture的handle方法表示,某个任务执行完成后,执行回调方法,并且是有返回值的;并且handle方法返回的CompletableFuture的result是回调方法执行的结果。
CompletableFuture<String> orgFuture = CompletableFuture.supplyAsync( () -> { System.out.println("当前线程名称:" + Thread.currentThread().getName()); try { Thread.sleep(2000L); } catch (InterruptedException e) { e.printStackTrace(); } return "任务一返回结果"; } ); CompletableFuture<String> rstFuture = orgFuture.handle((a, throwable) -> { System.out.println("当前线程名称:" + Thread.currentThread().getName()); System.out.println("上个任务执行完啦,还把" + a + "传过来"); if ("任务一返回结果".equals(a)) { System.out.println("一致"); } return "任务二返回值"; }); System.out.println(rstFuture.get());thenCombine / thenAcceptBoth / runAfterBoth都表示:将两个CompletableFuture组合起来,只有这两个都正常执行完了,才会执行某个任务。
区别在于:
thenCombine:会将两个任务的执行结果作为方法入参,传递到指定方法中,且有返回值
thenAcceptBoth: 会将两个任务的执行结果作为方法入参,传递到指定方法中,且无返回值
runAfterBoth 不会把执行结果当做方法入参,且没有返回值 这三个都可以用后面的AllOf代替
CompletableFuture<String> first = CompletableFuture.completedFuture("第一个异步任务"); ExecutorService executor = Executors.newFixedThreadPool(10); CompletableFuture<String> future = CompletableFuture //第二个异步任务 .supplyAsync(() -> "第二个异步任务", executor) // (w, s) -> System.out.println(s) 是第三个任务 .thenCombineAsync(first, (s, w) -> { System.out.println(w); System.out.println(s); return "两个异步任务的组合"; }, executor); System.out.println(future.join()); executor.shutdown();applyToEither / acceptEither / runAfterEither 都表示:将两个CompletableFuture组合起来,只要其中一个执行完了,就会执行某个任务。
区别在于:
applyToEither:会将已经执行完成的任务,作为方法入参,传递到指定方法中,且有返回值
acceptEither: 会将已经执行完成的任务,作为方法入参,传递到指定方法中,且无返回值
runAfterEither: 不会把执行结果当做方法入参,且没有返回值。 这三个都可以用后面的anyof代替
//第一个异步任务,休眠2秒,保证它执行晚点 CompletableFuture<String> first = CompletableFuture.supplyAsync(()->{ try{ Thread.sleep(2000L); System.out.println("执行完第一个异步任务");} catch (Exception e){ return "第一个任务异常"; } return "第一个异步任务"; }); ExecutorService executor = Executors.newSingleThreadExecutor(); CompletableFuture<Void> future = CompletableFuture //第二个异步任务 .supplyAsync(() -> { System.out.println("执行完第二个任务"); return "第二个任务";} , executor) //第三个任务 .acceptEitherAsync(first, System.out::println, executor); executor.shutdown();AllOf:所有任务都执行完成后,才执行 allOf返回的CompletableFuture。如果任意一个任务异常,allOf的CompletableFuture,执行get方法,会抛出异常
需要注意的是,由于allof是获取所有CompletableFuture对象的结果,因此无法确认返回的类型,所以allof返回的是CompletableFuture<void>对象
CompletableFuture<Void> a = CompletableFuture.runAsync(()->{ System.out.println("我执行完了"); }); CompletableFuture<Void> b = CompletableFuture.runAsync(() -> { System.out.println("我也执行完了"); }); CompletableFuture<Void> allOfFuture = CompletableFuture.allOf(a, b).whenComplete((m,k)->{ System.out.println("finish"); });任意一个任务执行完,就执行anyOf返回的CompletableFuture。如果执行的任务异常,anyOf的CompletableFuture,执行get方法,会抛出异常
CompletableFuture<Void> a = CompletableFuture.runAsync(()->{ try { Thread.sleep(3000L); } catch (InterruptedException e) { e.printStackTrace(); } System.out.println("我执行完了"); }); CompletableFuture<Void> b = CompletableFuture.runAsync(() -> { System.out.println("我也执行完了"); }); CompletableFuture<Object> anyOfFuture = CompletableFuture.anyOf(a, b).whenComplete((m,k)->{ System.out.println("finish"); });CompletableFuture使用需要注意的几点:
1- Future需要获取返回值,才能获取异常信息
2-自定义线程池时,注意饱和策略,如果线程池拒绝策略是DiscardPolicy或者DiscardOldestPolicy,
当线程池饱和时,会直接丢弃任务,不会抛弃异常。因此建议,CompletableFuture线程池策略最好使用AbortPolicy(线程池默认的拒绝策略,它会丢弃任务并抛出 `RejectedExecutionException` 异常。这有助于及时反馈程序运行状态),然后耗时的异步线程,做好线程池隔离
ExecutorService executorService = new ThreadPoolExecutor(5, 10, 5L, TimeUnit.SECONDS, new ArrayBlockingQueue<>(10)); CompletableFuture<Void> future = CompletableFuture.supplyAsync(() -> { int a = 0; int b = 666; int c = b / a; return true; },executorService).thenAccept(System.out::println);总结:
thenRun,thenAccept,thenApply和他们的异步方法都是代表下一步要做的任务,只是有没有参数和返回值的区别
CompletableFuture常用的几个方法:
两个创建异步任务方法: runAsync-没有返回值,supplyAsync-支持返回值
三个开启下个任务的thenXXX方法
两个获取结果方法: get,join ,
allOf,anyOf方法, 其他用的不多 标签:System,如何,任务,CompletableFuture,使用,println,返回值,out From: https://www.cnblogs.com/1--2/p/17974921