找回密码
 立即注册
首页 业界区 业界 Java源码分析系列笔记-15.CompletableFuture

Java源码分析系列笔记-15.CompletableFuture

陶田田 2025-9-25 20:58:48
目录

  • 1. 是什么
  • 2. Future VS CompletableFutre
  • 3. 使用

    • 3.1. 运行一个不返回结果的任务
    • 3.2. 运行一个返回结果的任务
    • 3.3. 线程池
    • 3.4. 手动完成任务
    • 3.5. 回调
    • 3.6. 链式调用
    • 3.7. 组合多个CompletableFuture
    • 3.8. 异常处理

  • 4. 源码分析

    • 4.1. 类图
    • 4.2. 属性

      • 4.2.1. AltResult

    • 4.3. runAsync

      • 4.3.1. 初始化默认的线程池
      • 4.3.2. 把执行的任务【Runnable】和接收结果【CompletableFuture】封装到AsyncRun
      • 4.3.3. 调用线程池的execute方法执行上面的AsyncRun

    • 4.4. supplyAsync

      • 4.4.1. 初始化默认的线程池
      • 4.4.2. 把执行的任务【Supplier】和接收结果【CompletableFuture】封装到AsyncSupply
      • 4.4.3. 调用线程池的execute方法执行上面的AsyncRun

    • 4.5. complete

      • 4.5.1. 手动设置结果
      • 4.5.2. 执行钩子方法


  • 5. 参考

1. 是什么

用于异步编程。(准备说是非阻塞)
Java中所谓的异步编程其实就是把阻塞的代码放在一个单独的线程中执行,并且有结果时会通知主线程
2. Future VS CompletableFutre

FutureCompletableFutre结果获取方式主动轮询。使用isDone来检查调用是否完成,get用来获取执行的结果异步回调。使用回调函数异常处理不支持支持链式调用不支持支持可以手动完成一个任务不支持支持3. 使用

3.1. 运行一个不返回结果的任务
  1. CompletableFuture<Void> future = CompletableFuture.runAsync(() -> {
  2.         try
  3.         {
  4.             TimeUnit.SECONDS.sleep(5);
  5.         }
  6.         catch (InterruptedException e)
  7.         {
  8.             throw new IllegalStateException(e);
  9.         }
  10.         System.out.println("后台任务完成");
  11.     });
  12.     future.get();
复制代码
3.2. 运行一个返回结果的任务
  1. CompletableFuture<String> future = CompletableFuture.supplyAsync(() -> {
  2.         try
  3.         {
  4.             TimeUnit.SECONDS.sleep(5);
  5.         }
  6.         catch (InterruptedException e)
  7.         {
  8.             throw new IllegalStateException(e);
  9.         }
  10.        return "后台任务完成";
  11.     });
  12.     String s = future.get();
  13.     System.out.println(s);
复制代码
3.3. 线程池

默认使用ForkJoin的commonpool里的线程池执行任务,但是也可以使用Executor作为第二个参数指定运行的线程池
  1. Executor executor = Executors.newFixedThreadPool(10);
  2. CompletableFuture<String> future = CompletableFuture.supplyAsync(() -> {
  3. try {
  4.     TimeUnit.SECONDS.sleep(1);
  5. } catch (InterruptedException e) {
  6.     throw new IllegalStateException(e);
  7. }
  8. return "Result of the asynchronous computation";
  9. }, executor);
复制代码
3.4. 手动完成任务
  1. CompletableFuture<String> stringCompletableFuture = new CompletableFuture<>();
  2.     new Thread(()->{
  3.         try
  4.         {
  5.             TimeUnit.SECONDS.sleep(5);
  6.         }
  7.         catch (InterruptedException e)
  8.         {
  9.             e.printStackTrace();
  10.         }
  11.        stringCompletableFuture.complete("手动完成任务");
  12.     }).run();
  13.     String s = stringCompletableFuture.get();
  14.     System.out.println(s);
复制代码
3.5. 回调


  • thenApply() 接受结果作为参数,有返回
  • thenAccept() 接受结果作为参数,无返回
  • thenRun() 无参数,无返回
  1. System.out.println("start");
  2.     CompletableFuture<String> future = CompletableFuture.supplyAsync(() -> {
  3.         try
  4.         {
  5.             TimeUnit.SECONDS.sleep(5);
  6.         }
  7.         catch (InterruptedException e)
  8.         {
  9.             throw new IllegalStateException(e);
  10.         }
  11.         return "后台任务完成";
  12.     });
  13.     future.thenAccept(System.out::println);
  14.     System.out.println("主线程继续执行并且休眠10s");
  15.     TimeUnit.SECONDS.sleep(10);
复制代码
3.6. 链式调用
  1. System.out.println("start");
  2.     CompletableFuture<String> future = CompletableFuture.supplyAsync(() -> {
  3.         try
  4.         {
  5.             TimeUnit.SECONDS.sleep(5);
  6.         }
  7.         catch (InterruptedException e)
  8.         {
  9.             throw new IllegalStateException(e);
  10.         }
  11.         return "后台任务完成";
  12.     });
  13.     future.thenApply(s->{
  14.         System.out.println(Thread.currentThread().getName() + "s");
  15.         return s;
  16.     }).thenApply(s->{
  17.         System.out.println(Thread.currentThread().getName() + "s");
  18.         return s;
  19.     });
  20.     System.out.println("主线程继续执行并且休眠10s");
  21.     TimeUnit.SECONDS.sleep(10);
复制代码
3.7. 组合多个CompletableFuture


  • thenCompose() 有依赖的两个Future
  • thenCombine() 没有依赖的两个Future
  • CompletableFuture.allOf 所有Future完成
  • CompletableFuture.anyOf 任意一个Future完成
  1. System.out.println("start runnning............");
  2.     long start = System.currentTimeMillis();
  3.     CompletableFuture<String> future1
  4.             = CompletableFuture.supplyAsync(() ->
  5.             {
  6.                 try
  7.                 {
  8.                     TimeUnit.SECONDS.sleep(5);
  9.                 }
  10.                 catch (InterruptedException e)
  11.                 {
  12.                     e.printStackTrace();
  13.                 }
  14.                 System.out.println("Hello" + Thread.currentThread().getName());
  15.                 return "Hello";
  16.             }
  17.     );
  18.     CompletableFuture<String> future2
  19.             = CompletableFuture.supplyAsync(() ->
  20.             {
  21.                 try
  22.                 {
  23.                     TimeUnit.SECONDS.sleep(8);
  24.                 }
  25.                 catch (InterruptedException e)
  26.                 {
  27.                     e.printStackTrace();
  28.                 }
  29.                 System.out.println("Beautiful" + Thread.currentThread().getName());
  30.                 return "Beautiful";
  31.             }
  32.     );
  33.     CompletableFuture<String> future3
  34.             = CompletableFuture.supplyAsync(() ->
  35.             {
  36.                 try
  37.                 {
  38.                     TimeUnit.SECONDS.sleep(10);
  39.                 }
  40.                 catch (InterruptedException e)
  41.                 {
  42.                     e.printStackTrace();
  43.                 }
  44.                 System.out.println("World" + Thread.currentThread().getName());
  45.                 return "World";
  46.             }
  47.     );
  48.     CompletableFuture<Void> combinedFuture
  49.             = CompletableFuture.allOf(future1, future2, future3);
  50.     combinedFuture.get();
  51.     long end = System.currentTimeMillis();
  52.     System.out.println("finish run...time is " + (end-start));
  53.     assertTrue(future1.isDone());
  54.     assertTrue(future2.isDone());
  55.     assertTrue(future3.isDone());
  56.     System.out.println(future1.get());
  57.     System.out.println(future2.get());
  58.     System.out.println(future3.get());
复制代码
3.8. 异常处理


  • exceptionally发生异常的时候调用
  • handle无论发生异常与否都调用
  1. CompletableFuture<Object> future = CompletableFuture.supplyAsync(() -> {
  2.             throw new IllegalArgumentException("Age can not be negative");
  3.     }).exceptionally(ex -> {
  4.         System.out.println("Oops! We have an exception - " + ex.getMessage());
  5.         return "Unknown!";
  6.     });
  7. System.out.println(future.get());
复制代码
4. 源码分析

4.1. 类图

1.png

可以看出CompletableFuture实现了Future接口,因此这玩意也是一个可以获取异步执行结果的接口
4.2. 属性
  1. volatile Object result;       // Either the result or boxed AltResult
  2. volatile Completion stack;    // Top of Treiber stack of dependent actions
复制代码
运行的结果存在Object result,如果发生了异常那么封装在AltResult
4.2.1. AltResult
  1. static final class AltResult { // See above
  2.     final Throwable ex;        // null only for NIL
  3.     AltResult(Throwable x) { this.ex = x; }
  4. }
  5. /** The encoding of the null value. */
  6. static final AltResult NIL = new AltResult(null);
复制代码
4.3. runAsync
  1. public static CompletableFuture<Void> runAsync(Runnable runnable) {
  2.     return asyncRunStage(asyncPool, runnable);
  3. }
复制代码
传入asyncPool和runnable任务调用asyncRunStage方法
我们先看看asyncPool是怎么初始化的
4.3.1. 初始化默认的线程池
  1. //返回true
  2. private static final boolean useCommonPool =
  3.     (ForkJoinPool.getCommonPoolParallelism() > 1);
  4. //这里使用的是ForkJoinPool.commonPool()
  5. private static final Executor asyncPool = useCommonPool ?
  6.     ForkJoinPool.commonPool() : new ThreadPerTaskExecutor();
复制代码
所以默认使用的是ForkJoinPool.commonPool()
有了默认的线程池,接下来调用的asyncRunStage方法

  • asyncRunStage
  1. static CompletableFuture<Void> asyncRunStage(Executor e, Runnable f) {
  2.     if (f == null) throw new NullPointerException();
  3.     CompletableFuture<Void> d = new CompletableFuture<Void>();
  4.     e.execute(new AsyncRun(d, f));
  5.     return d;
  6. }
复制代码

  • 2行:任务为空那么抛出异常
  • 3行:构造CompletableFuture,用于接收结果
  • 4行:先用CompletableFuture和Runnable构造AsyncRun,接口调用线程池Executor的execute方法执行这个AsyncRun
  • 5行:返回CompletableFuture
4.3.2. 把执行的任务【Runnable】和接收结果【CompletableFuture】封装到AsyncRun

先看看AsyncRun类

  • AsyncRun
  1. static final class AsyncRun extends ForkJoinTask<Void>
  2.         implements Runnable, AsynchronousCompletionTask {
  3.     CompletableFuture<Void> dep; Runnable fn;
  4.     AsyncRun(CompletableFuture<Void> dep, Runnable fn) {
  5.         this.dep = dep; this.fn = fn;
  6.     }
  7.     public final Void getRawResult() { return null; }
  8.     public final void setRawResult(Void v) {}
  9.     public final boolean exec() { run(); return true; }
  10.     public void run() {
  11.         CompletableFuture<Void> d; Runnable f;
  12.         if ((d = dep) != null && (f = fn) != null) {
  13.             //清空CompletableFuture和Runnable
  14.             dep = null; fn = null;
  15.             //如果CompletableFuture的结果为空
  16.             if (d.result == null) {
  17.                 try {
  18.                     //那么执行Runnable方法
  19.                     f.run();
  20.                     //CAS设置CompletableFuture的结果为AltResult NIL--详见上面的AltResult
  21.                     d.completeNull();
  22.                 } catch (Throwable ex) {
  23.                     //抛出了异常则CAS设置CompletableFuture的结果为AltResult(异常)--详见上面的AltResult
  24.                     d.completeThrowable(ex);
  25.                 }
  26.             }
  27.             d.postComplete();
  28.         }
  29.     }
  30. }
复制代码

  • 2行:实现了Runnable接口
  • 4-6行:构造方法只是保存了传进来的Runnable和CompletableFuture
  • 12-26行:线程池的execute方法最终会调用这个run方法。详细说明见注释。
我们可以看看设置null结果和异常结果的方法

  • completeNull【null】
  1. final boolean completeNull() {
  2.     //CAS设置RESULT为NIL
  3.     return UNSAFE.compareAndSwapObject(this, RESULT, null,
  4.                                        NIL);
  5. }
复制代码

  • completeThrowable【异常】
  1. static AltResult encodeThrowable(Throwable x) {
  2.     return new AltResult((x instanceof CompletionException) ? x :
  3.                          new CompletionException(x));
  4. }
  5. /** Completes with an exceptional result, unless already completed. */
  6. final boolean completeThrowable(Throwable x) {
  7.     //CAS设置RESULT为AltResult(异常)
  8.     return UNSAFE.compareAndSwapObject(this, RESULT, null,
  9.                                        encodeThrowable(x));
  10. }
复制代码
4.3.3. 调用线程池的execute方法执行上面的AsyncRun

执行AsyncRun的时候最终会调用AsyncRun的run方法,分析如上面的把执行的任务【Runnable】和接收结果【CompletableFuture】封装到AsyncRun
4.4. supplyAsync
  1. public static <U> CompletableFuture<U> supplyAsync(Supplier<U> supplier) {
  2.     return asyncSupplyStage(asyncPool, supplier);
  3. }
复制代码
传入默认的线程池asyncPool和任务supplier,这个supplier是Supplier【函数式接口】,如下图:
2.png

4.4.1. 初始化默认的线程池

初始化默认的线程池跟上面的runAsync一样
我们接着跟踪asyncSupplyStage方法

  • asyncSupplyStage
  1. static <U> CompletableFuture<U> asyncSupplyStage(Executor e,
  2.                                                  Supplier<U> f) {
  3.     if (f == null) throw new NullPointerException();
  4.     CompletableFuture<U> d = new CompletableFuture<U>();
  5.     e.execute(new AsyncSupply<U>(d, f));
  6.     return d;
  7. }
复制代码

  • 2行:任务为空那么抛出异常
  • 3行:构造CompletableFuture,用于接收结果
  • 4行:先用CompletableFuture和Supplier构造AsyncSupply,接口调用线程池Executor的execute方法执行这个AsyncSupply
  • 5行:返回CompletableFuture
4.4.2. 把执行的任务【Supplier】和接收结果【CompletableFuture】封装到AsyncSupply


  • AsyncSupply
  1. static final class AsyncSupply<T> extends ForkJoinTask<Void>
  2.         implements Runnable, AsynchronousCompletionTask {
  3.     CompletableFuture<T> dep; Supplier<T> fn;
  4.     AsyncSupply(CompletableFuture<T> dep, Supplier<T> fn) {
  5.         this.dep = dep; this.fn = fn;
  6.     }
  7.     public final Void getRawResult() { return null; }
  8.     public final void setRawResult(Void v) {}
  9.     public final boolean exec() { run(); return true; }
  10.     public void run() {
  11.         CompletableFuture<T> d; Supplier<T> f;
  12.         if ((d = dep) != null && (f = fn) != null) {
  13.             //清空CompletableFuture和Runnable
  14.             dep = null; fn = null;
  15.             //如果CompletableFuture的结果为空
  16.             if (d.result == null) {
  17.                 try {
  18.                     //调用Supplier.get获取结果
  19.                     //然后调用CompletableFuture.completeValue把结果设置进
  20.                     d.completeValue(f.get());
  21.                 } catch (Throwable ex) {
  22.                     //抛出了异常则CAS设置CompletableFuture的结果为AltResult(异常)--详见上面的AltResult
  23.                     d.completeThrowable(ex);
  24.                 }
  25.             }
  26.             d.postComplete();
  27.         }
  28.     }
  29. }
复制代码

  • 2行:实现了Runnable接口
  • 4-6行:构造方法只是保存了传进来的Runnable和CompletableFuture
  • 12-26行:线程池的execute方法最终会调用这个run方法。详细说明见注释。
我们可以看看设置结果的completeValue方法

  • completeValue
  1. final boolean completeValue(T t) {
  2.     return UNSAFE.compareAndSwapObject(this, RESULT, null,
  3.                                        (t == null) ? NIL : t);
  4. }
复制代码
4.4.3. 调用线程池的execute方法执行上面的AsyncRun

执行AsyncRun的时候最终会调用AsyncRun的run方法,分析如上面的把执行的任务【Supplier】和接收结果【CompletableFuture】封装到AsyncSupply
4.5. complete
  1. public boolean complete(T value) {
  2.     boolean triggered = completeValue(value);
  3.     postComplete();
  4.     return triggered;
  5. }
复制代码

  • 2行:手动设置结果
  • 3行:执行钩子方法
4.5.1. 手动设置结果
  1. final boolean completeValue(T t) {
  2.     return UNSAFE.compareAndSwapObject(this, RESULT, null,
  3.                                        (t == null) ? NIL : t);
  4. }
复制代码
4.5.2. 执行钩子方法

这段代码确定没看懂要干啥
  1. final void postComplete() {
  2.     /*
  3.      * On each step, variable f holds current dependents to pop
  4.      * and run.  It is extended along only one path at a time,
  5.      * pushing others to avoid unbounded recursion.
  6.      */
  7.     CompletableFuture<?> f = this; Completion h;
  8.     while ((h = f.stack) != null ||
  9.            (f != this && (h = (f = this).stack) != null)) {
  10.         CompletableFuture<?> d; Completion t;
  11.         if (f.casStack(h, t = h.next)) {
  12.             if (t != null) {
  13.                 if (f != this) {
  14.                     pushStack(h);
  15.                     continue;
  16.                 }
  17.                 h.next = null;    // detach
  18.             }
  19.             f = (d = h.tryFire(NESTED)) == null ? this : d;
  20.         }
  21.     }
  22. }
复制代码
5. 参考


  • Java 8 CompletableFuture 教程 - 掘金

来源:程序园用户自行投稿发布,如果侵权,请联系站长删除
免责声明:如果侵犯了您的权益,请联系站长,我们会及时删除侵权内容,谢谢合作!

相关推荐

您需要登录后才可以回帖 登录 | 立即注册