CompletableFuture

CompletableFuture提供了一种观察者模式类似机制,可以让任务执行完成后通知监听的一方。
1 Future
Future提供异步并行计算功能,如果主线程需要一个很耗时的计算任务,我们可以通过Future把这个任务放在异步线程去执行,
主线程则去执行其他任务,处理完后,再用Future获取结果。
但是Future对于结果的获取并不是很友好,只能通过阻塞或轮询的方式得到任务的结果,Future.get()就是阻塞调用,
在线程获取结果之前get方法会一直阻塞,Future提供了isDone方法,可以在程序中使用这个方法查询执行结果
Demo:
Future操作

/**
 * Future 
 * Future
 * Future
 * Future
 *
 * Result:
 * calFuncTask: 4673466.899862001
 * calFuncTask1: 32022.75379807269
 * TimeCost: 822
 *
 * Future
 * Future.get()get
 * FutureisDone
 */
 @Test
 public void futureTest() throws InterruptedException, ExecutionException {
 ExecutorService executorService = Executors.newFixedThreadPool(10);
 // 
 long startTime = System.currentTimeMillis();
 // 
 FutureTask<Double> calFuncTask = new FutureTask<>(() -> {
 Thread.sleep(300);
 return 19*28.3*65.4*132.8989;
 });
 executorService.submit(calFuncTask);
 // 
 Thread.sleep(300);
 // 
 FutureTask<Double> calFuncTask1 = new FutureTask<>(() -> {
 Thread.sleep(500);
 return 19.313*2.3*5.4245*132.8989;
 });
 executorService.submit(calFuncTask1);
 // isDone
 boolean done = false;
 while(!done){
 done = calFuncTask1.isDone();
 Thread.sleep(50);
 System.out.println("calFuncTask1: " + done);
 }
 System.out.println("calFuncTask: " + calFuncTask.get() + "\n" + "calFuncTask1: " + calFuncTask1.get() + 
"\n" + "TimeCost: " + (System.currentTimeMillis() - startTime));
 }

2 CompletableFuture
CompletableFuture提供了一种观察者模式类似机制,可以让任务执行完成后通知监听的一方。
Completable 三个使用场景:
1 创建异步任务
2 简单任务异步回调
3 多任务组合处理
supplyAsync执行CompletableFuture任务,支持返回值。
runAsync执行CompletableFuture任务,没有返回值。
Demo:
CompletableFuture操作

/**
 * CompletableFuture
 * CompletableFuture
 *
 * Result:
 * calFuncTask: 4673466.899862001
 * calFuncTask1: 32022.75379807269
 * TimeCost: 582
 *
 * Completable 
 * 
 * 
 * 
 * supplyAsyncCompletableFuture
 * runAsyncCompletableFuture
 *
 */
 @Test
 public void completableFutureTest() throws InterruptedException, ExecutionException, TimeoutException {
 // 
 long startTime = System.currentTimeMillis();
 // 
 CompletableFuture<Double> calFuncTask = CompletableFuture.supplyAsync(() -> {
 try {
 Thread.sleep(300);
 } catch (InterruptedException e) {
 throw new RuntimeException(e);
 }
 return 19*28.3*65.4*132.8989;
 });
 // 
 CompletableFuture<Double> calFuncTask1 = CompletableFuture.supplyAsync(() -> {
 try {
 Thread.sleep(500);
 } catch (InterruptedException e) {
 throw new RuntimeException(e);
 }
 return 19.313*2.3*5.4245*132.8989;
 });
 // 
 Thread.sleep(300);
 // 
 boolean done = false;
 while(!done){
 done = calFuncTask1.isDone();
 Thread.sleep(50);
 System.out.println("calFuncTask1 Status: " + done);
 }
 Double result = calFuncTask.get(2, TimeUnit.SECONDS);
 Double result1 = calFuncTask1.get();
 System.out.println("calFuncTask: " + result + "\n" + "calFuncTask1: " + result1 + "\n" + "TimeCost: " + 
(System.currentTimeMillis() - startTime));
 }

3 CompletableFuture 任务异步回调
3.1 thenRun / thenRunAsync
public CompletableFuture thenRun(Runnable action);
public CompletableFuture thenRunAsync(Runnable action);
CompletableFuture的thenRun方法,就是做完第一个任务后,再做第二个任务,某个任务执行完成后,执行回调方法,但是前后两个任务没有参数的传递,
第二个任务也没有返回值。
thenRun 和 thenRunSync 的区别
如果执行第一个任务的时候,传入了一个自定义的线程池:
调用thenRun方法执行第二个任务时,第二个任务和第一个任务使用的同一线程池
调用thenRunAsync方法执行第二个任务时,第一个任务使用自定义,而第二个使用ForkJoinPool
后续的区别和这个一样
Demo:

thenRun / thenRunAsync
 /**
 * CompletableFuture 
 * 1. thenRun/thenRunSync
 * CompletableFuturethenRun
 * 
 *
 * Result:
 * orgFuture called
 * Then we go thenRunFuture
 * null
 *
 * thenRun thenRunSync 
 * :
 * thenRun
 * thenRunAsyncForkJoinPool
 */
 @Test
 public void thenRunTest() throws ExecutionException, InterruptedException {
 // Future
 CompletableFuture<String> orgFuture = CompletableFuture.supplyAsync(() -> {
 System.out.println("orgFuture called");
 return "orgFuture result";
 });
 // Future
 CompletableFuture<Void> thenRunFuture = orgFuture.thenRun(() -> {
 System.out.println("Then we go thenRunFuture");
 });
 System.out.println(thenRunFuture.get());
 }

3.2 thenAccept / thenAcceptAsync
CompletableFuture的thenAccept方法表示,第一个任务执行完成后,执行第二个回调方法任务,
会将该任务的执行结果,作为入参,传递到回调方法中,但是回调方法是没有返回值的。
Demo:
thenAccept / thenAcceptAsync

 /**
 * 2. thenAccept/thenAcceptAsync
 * CompletableFuturethenAccept
 * 
 *
 * Result:
 * orgFuture called
 * thenAcceptFuture validation successfully
 * thenAcceptFuture end
 * null
 */
 @Test
 public void thenAcceptTest() throws ExecutionException, InterruptedException {
 // 
 CompletableFuture<String> orgFuture = CompletableFuture.supplyAsync(() -> {
 System.out.println("orgFuture called");
 return "the result of orgFuture";
 });
 // 
 CompletableFuture<Void> thenAcceptFuture = orgFuture.thenAccept((result) -> {
 if (result.equals("the result of orgFuture")){
 System.out.println("thenAcceptFuture validation successfully");
 }
 System.out.println("thenAcceptFuture end");
 });
 System.out.println(thenAcceptFuture.get());
 }

3.3 thenApply / thenApplyAsync
CompletableFuture的thenApply方法表示,第一个任务执行完成后,执行第二个回调方法任务,
会将该任务的执行结果,作为入参,传递到回调方法中,并且回调方法是有返回值的。
Demo:
thenApply / thenApplyAsync

/**
 * 3. thenApply/thenApplyAsync
 * CompletableFuturethenApply
 * 
 *
 * Result:
 * orgFuture called
 * thenApplyFuture Validation Success
 */
 @Test
 public void thenApplyTest() throws ExecutionException, InterruptedException {
 // 
 CompletableFuture<String> orgFuture = CompletableFuture.supplyAsync(() -> {
 System.out.println("orgFuture called");
 return "the result of orgFuture";
 });
 // 
 CompletableFuture<String> thenApplyFuture = orgFuture.thenApply((result) -> {
 if (result.equals("the result of orgFuture")){
 return "thenApplyFuture Validation Success";
 }
 return "thenApplyFuture Validation Failed";
 });
 System.out.println(thenApplyFuture.get());
 }

3.4 exceptionally
CompletableFuture的exceptionally方法表示,某个任务执行异常时,执行的回调方法;并且用抛出异常作为参数,传递到回调方法.
Demo:
exceptionally

/**
 * 4. exceptionally
 * CompletableFutureexceptionally
 * 
 *
 * Result:
 * Current thread name: ForkJoinPool.commonPool-worker-19
 * java.util.concurrent.CompletionException: java.lang.RuntimeException: Exception created by orgFuture
 * ...
 * Caused by: java.lang.RuntimeException: Exception created by orgFuture
 * ...
 * Program Run Failed
 */
 @Test
 public void exceptionallyTest() throws ExecutionException, InterruptedException {
 // 
 CompletableFuture<String> orgFuture = CompletableFuture.supplyAsync(() -> {
 System.out.println("Current thread name: " + Thread.currentThread().getName());
 throw new RuntimeException("Exception created by orgFuture");
 });
 // 
 CompletableFuture<String> exceptionallyFuture = orgFuture.exceptionally((e) -> {
 e.printStackTrace();
 return "Program Run Failed";
 });
 System.out.println(exceptionallyFuture.get());
 }

3.5 whenComplete
CompletableFuture的whenComplete方法表示,某个任务执行完成后,执行的回调方法,无返回值;
并且whenComplete方法返回的CompletableFuture的result是上个任务的结果。
Demo:
whenComplete

/**
 * 5. whenComplete
 * CompletableFuturewhenComplete
 * whenCompleteCompletableFutureresult
 * <p>
 * Result:
 * Current Thread Name: ForkJoinPool.commonPool-worker-19
 * Current Thread Name: ForkJoinPool.commonPool-worker-19
 * The result of orgFuture: Result of orgFuture
 * whenCompleteFuture Validation Completed
 * Result of whenCompleteFuture: Result of orgFuture
 */
 @Test
 public void whenCompleteTest() throws ExecutionException, InterruptedException {
 // 
 CompletableFuture<String> orgFuture = CompletableFuture.supplyAsync(() -> {
 System.out.println("Current Thread Name: " + Thread.currentThread().getName());
 try {
 Thread.sleep(2000);
 } catch (InterruptedException e) {
 throw new RuntimeException(e);
 }
 return "Result of orgFuture";
 });
 // 
 CompletableFuture<String> whenCompleteFuture = orgFuture.whenComplete((result, throwable) -> {
 System.out.println("Current Thread Name: " + Thread.currentThread().getName());
 System.out.println("The result of orgFuture: " + result);
 if (result.equals("Result of orgFuture")) {
 System.out.println("whenCompleteFuture Validation Completed");
 } else {
 System.out.println("whenCompleteFuture Validation Failed");
 }
 });
 System.out.println("Result of whenCompleteFuture: " + whenCompleteFuture.get());
 }

3.6 handle
CompletableFuture的handle方法表示,某个任务执行完成后,执行回调方法,并且是有返回值的;
并且handle方法返回的CompletableFuture的result是回调方法执行的结果。
不同的是 handle 是在任务完成后再执行,还可以处理异常的任务。
thenApply 只可以执行正常的任务,任务出现异常则不执行 thenApply 方法
Demo:
handle

/**
 * 6. handle
 * CompletableFuturehandle;
 * handleCompletableFutureresult
 * handle thenApply thenApply 
 * <p>
 * Result:
 * Current Thread Name: ForkJoinPool.commonPool-worker-19
 * handleFuture Validation Completed
 */
 @Test
 public void handleTest() throws ExecutionException, InterruptedException {
 // 
 CompletableFuture<String> orgFuture = CompletableFuture.supplyAsync(() -> {
 System.out.println("Current Thread Name: " + Thread.currentThread().getName());
 try {
 Thread.sleep(2000);
 } catch (InterruptedException e) {
 throw new RuntimeException(e);
 }
 return "orgFuture Result";
 });
 // 
 CompletableFuture<String> handleFuture = orgFuture.handle((result, throwable) -> {
 if ("orgFuture Result".equals(result)){
 return "handleFuture Validation Completed";
 }else{
 return "handleFuture Validation Failed";
 }
 });
 System.out.println(handleFuture.get());
 }

4 CompletableFuture多个任务组合处理
5 ForkJoinPool
ForkJoinPool和ThreadPoolExecutor都是继承自AbstractExecutorService抽象类,所以它和ThreadPoolExecutor的使用几乎没有多少区别,除了任务变成了
ForkJoinTask以外。
ForkJoinPool和ThreadPoolExecutor最主要的区别就是ForkJoinPool中每一个线程都有属于自己的队列,
当某个线程队列任务全部执行完了时,会通过"窃取工作"从别的线程队列中取出一个任务进行执行。
具体的策略就是每一个线程维护一个自己的队列,先进后出(FILO)将任务塞到队列的头部,
执行任务时从队列头部取出任务执行。其他线程从队列尾部窃取任务执行。减少阻塞消耗,特别适用于计算型任务。

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值