CompletableFuture源碼分析

返回主頁

簡介

先說Future, 它用來描述一個異步計算的結果。isDone方法可以用來檢查計算是否完成,get方法可以用來獲取結果,直到完成前一直阻塞當前線程,cancel方法可以取消任務。而對於結果的獲取,只能通過阻塞(get())或者輪詢的方式[while(!isDone)]. 阻塞的方式違背了異步編程的理念,輪詢的方式耗費無謂的CPU資源(CPU空轉)。於是,CompletableFuture應運而生。

樣例

後面介紹的源碼都會以下面的用例爲切入點,循着調用軌跡理解源碼。如果任務很耗時,記得傳Executor, 或者方法末尾加上future.get(); 因爲CompletableFuture默認使用ForkJoinPool, 而ForkJoinPool裏面的線程都是daemon線程,主線程跑完了,虛擬機也就over了。

複製代碼

 1     public void whenComplete() { 2         CompletableFuture<Integer> future = CompletableFuture.supplyAsync(() -> 100); 3         future.whenComplete((l, r) -> System.out.println(l)); 4     } 5  6     public void thenApply() { 7         CompletableFuture<Integer> future = CompletableFuture.supplyAsync(() -> 100); 8         future.thenApply(i -> -i); 9     }10 11     public void thenAccept() {12         CompletableFuture<Integer> future = CompletableFuture.supplyAsync(() -> 100);13         future.thenAccept(System.out::println);14     }15 16     public void thenRun() {17         CompletableFuture<Integer> future = CompletableFuture.supplyAsync(() -> 100);18         future.thenRun(() -> System.out.println("Done"));19     }20 21     public void thenAcceptBoth() {22         CompletableFuture<Integer> future = CompletableFuture.supplyAsync(() -> 100);23         CompletableFuture<Integer> other = CompletableFuture.supplyAsync(() -> 200);24         future.thenAcceptBoth(other, (x, y) -> System.out.println(x + y));25     }26 27     public void acceptEither() {28         CompletableFuture<Integer> future = CompletableFuture.supplyAsync(() -> 100);29         CompletableFuture<Integer> other = CompletableFuture.supplyAsync(() -> 200);30         future.acceptEither(other, System.out::println);31 32     }33 34     public void allOf() {35         CompletableFuture<Integer> future = CompletableFuture.supplyAsync(() -> 100);36         CompletableFuture<Integer> second = CompletableFuture.supplyAsync(() -> 200);37         CompletableFuture<Integer> third = CompletableFuture.supplyAsync(() -> 300);38         CompletableFuture.allOf(future, second, third);39 40     }41 42     public void anyOf() throws InterruptedException, ExecutionException {43         CompletableFuture<Integer> future = CompletableFuture.supplyAsync(() -> 100);44         CompletableFuture<Integer> second = CompletableFuture.supplyAsync(() -> 200);45         CompletableFuture<Integer> third = CompletableFuture.supplyAsync(() -> 300);46         CompletableFuture.anyOf(future, second, third);47     }

複製代碼

 

源碼分析

supplyAsync

supplyAsync(Supplier<U> supplier)

1     public static <U> CompletableFuture<U> supplyAsync(Supplier<U> supplier) {2         return asyncSupplyStage(asyncPool, supplier); // asyncPool, ForkJoinPool.commonPool()或者ThreadPerTaskExecutor(實現了Executor接口,裏面的內容是{new Thread(r).start();})3     }

 

asyncSupplyStage(Executor e, Supplier<U> f)

複製代碼

1     static <U> CompletableFuture<U> asyncSupplyStage(Executor e, Supplier<U> f) {2         if (f == null)3             throw new NullPointerException();4         CompletableFuture<U> d = new CompletableFuture<U>(); // 構建一個新的CompletableFuture, 以此構建AsyncSupply作爲Executor的執行參數5         e.execute(new AsyncSupply<U>(d, f)); // AsyncSupply繼承了ForkJoinTask, 實現了Runnable, AsynchronousCompletionTask接口6         return d; // 返回d,立返7     }

複製代碼

 

AsyncSupply

複製代碼

 1     // CompletableFuture的靜態內部類,作爲一個ForkJoinTask 2     static final class AsyncSupply<T> extends ForkJoinTask<Void> implements Runnable, AsynchronousCompletionTask { 3         CompletableFuture<T> dep; // AsyncSupply作爲一個依賴Task,dep作爲這個Task的Future 4         Supplier<T> fn; // fn作爲這個Task的具體執行邏輯,函數式編程 5  6         AsyncSupply(CompletableFuture<T> dep, Supplier<T> fn) { 7             this.dep = dep; 8             this.fn = fn; 9         }10 11         public final Void getRawResult() {12             return null;13         }14 15         public final void setRawResult(Void v) {16         }17 18         public final boolean exec() {19             run();20             return true;21         }22 23         public void run() {24             CompletableFuture<T> d;25             Supplier<T> f;26             if ((d = dep) != null && (f = fn) != null) { // 非空判斷27                 dep = null;28                 fn = null;29                 if (d.result == null) { // 查看任務是否結束,如果已經結束(result != null),直接調用postComplete()方法30                     try {31                         d.completeValue(f.get()); // 等待任務結束,並設置結果32                     } catch (Throwable ex) {33                         d.completeThrowable(ex); // 異常34                     }35                 }36                 d.postComplete(); // 任務結束後,會執行所有依賴此任務的其他任務,這些任務以一個無鎖併發棧的形式存在37             }38         }39     }

複製代碼

 

postComplete()

複製代碼

 1     final void postComplete() { 2         CompletableFuture<?> f = this; // 當前CompletableFuture 3         Completion h; // 無鎖併發棧,(Completion next), 保存的是依靠當前的CompletableFuture一串任務,完成即觸發(回調) 4         while ((h = f.stack) != null || (f != this && (h = (f = this).stack) != null)) { // 當f的stack爲空時,使f重新指向當前的CompletableFuture,繼續後面的結點 5             CompletableFuture<?> d; 6             Completion t; 7             if (f.casStack(h, t = h.next)) { // 從頭遍歷stack,並更新頭元素 8                 if (t != null) { 9                     if (f != this) { // 如果f不是當前CompletableFuture,則將它的頭結點壓入到當前CompletableFuture的stack中,使樹形結構變成鏈表結構,避免遞歸層次過深10                         pushStack(h);11                         continue; // 繼續下一個結點,批量壓入到當前棧中12                     }13                     h.next = null; // 如果是當前CompletableFuture, 解除頭節點與棧的聯繫14                 }15                 f = (d = h.tryFire(NESTED)) == null ? this : d; // 調用頭節點的tryFire()方法,該方法可看作Completion的鉤子方法,執行完邏輯後,會向後傳播的16             }17         }18     }

複製代碼

 

示意圖

每個CompletableFuture持有一個Completion棧stack, 每個Completion持有一個CompletableFuture -> dep, 如此遞歸循環下去,是層次很深的樹形結構,所以想辦法將其變成鏈表結構。

首先取出頭結點,下圖中灰色Completion結點,它會返回一個CompletableFuture, 同樣也擁有一個stack,策略是遍歷這個CompletableFuture的stack的每個結點,依次壓入到當前CompletableFuture的stack中,關係如下箭頭所示,灰色結點指的是處理過的結點。

第一個Completion結點返回的CompletableFuture, 將擁有的stack裏面的所有結點都壓入了當前CompletableFuture的stack裏面

 

後續的Completion結點返回的CompletableFuture, 將擁有的stack裏面的所有結點都壓入了當前CompletableFuture的stack裏面,重新構成了一個鏈表結構,後續也按照前面的邏輯操作,如此反覆,便會遍歷完所有的CompletableFuture, 這些CompletableFuture(葉子結點)的stack爲空,也是結束條件。

 

postComplete()最後調用的是Completion#tryFire()方法,先看下Completion的數據結構

 

Completion

複製代碼

 1     abstract static class Completion extends ForkJoinTask<Void> implements Runnable, AsynchronousCompletionTask { 2         volatile Completion next; // 無鎖併發棧 3  4         /** 5          * 鉤子方法,有三種模式,postComplete()方法裏面使用的是NESTED模式,避免過深的遞歸調用 SYNC, ASYNC, or NESTED 6          */ 7         abstract CompletableFuture<?> tryFire(int mode); // run()和exec()都調用了這個鉤子方法 8  9         /** cleanStack()方法裏有用到 */10         abstract boolean isLive();11 12         public final void run() {13             tryFire(ASYNC);14         }15 16         public final boolean exec() {17             tryFire(ASYNC);18             return true;19         }20 21         public final Void getRawResult() {22             return null;23         }24 25         public final void setRawResult(Void v) {26         }27     }

複製代碼

static final int SYNC = 0;       同步
   static final int ASYNC  =  1;    異步
   static final int NESTED = -1; 嵌套

 

繼承了ForkJoinTask, 實現了Runnable, AsynchronousCompletionTask接口,它有諸多子類,如下圖

後面的方法都對應着不同的子類。 

先看一個子類UniCompletion

複製代碼

 1     abstract static class UniCompletion<T,V> extends Completion { 2         Executor executor;                 // 執行器 3         CompletableFuture<V> dep;          // 依賴的任務 4         CompletableFuture<T> src;          // 被依賴的任務 5  6         UniCompletion(Executor executor, CompletableFuture<V> dep, 7                       CompletableFuture<T> src) { 8             this.executor = executor; this.dep = dep; this.src = src; 9         }10 11         final boolean claim() { // 如果當前任務可以被執行,返回true,否則,返回false; 保證任務只被執行一次12             Executor e = executor;13             if (compareAndSetForkJoinTaskTag((short)0, (short)1)) {14                 if (e == null)15                     return true;16                 executor = null; // 設置爲不可用17                 e.execute(this);18             }19             return false;20         }21 22         final boolean isLive() { return dep != null; }23     }

複製代碼

 claim()方法保證任務只被執行一次。

 

whenComplete

whenComplete()/whenCompleteAsync()

複製代碼

1     public CompletableFuture<T> whenComplete(BiConsumer<? super T, ? super Throwable> action) {2         return uniWhenCompleteStage(null, action);3     }4 5     public CompletableFuture<T> whenCompleteAsync(BiConsumer<? super T, ? super Throwable> action) {6         return uniWhenCompleteStage(asyncPool, action);7     }

複製代碼

xxx和xxxAsync方法的區別是,有沒有asyncPool作爲入參,有的話,任務直接入參,不檢查任務是否完成。uniWhenCompleteStage方法有說明。

 

uniWhenCompleteStage(Executor e, BiConsumer<? super T, ? super Throwable> f)

複製代碼

 1     private CompletableFuture<T> uniWhenCompleteStage(Executor e, BiConsumer<? super T, ? super Throwable> f) { 2         if (f == null) 3             throw new NullPointerException(); 4         CompletableFuture<T> d = new CompletableFuture<T>(); // 構建future 5         if (e != null || !d.uniWhenComplete(this, f, null)) { // 如果線程池不爲空,直接構建任務入棧,並調用tryFire()方法;否則,調用uniWhenComplete()方法,檢查依賴的那個任務是否完成,沒有完成返回false, 6                                                                 // 完成了返回true, 以及後續一些操作。 7             UniWhenComplete<T> c = new UniWhenComplete<T>(e, d, this, f); // UniWhenComplete繼承了UniCompletion 8             push(c); 9             c.tryFire(SYNC); // 先調一下鉤子方法,檢查一下任務是否結束10         }11         return d;12     }

複製代碼

 

uniWhenComplete(CompletableFuture<T> a, BiConsumer<? super T, ? super Throwable> f, UniWhenComplete<T> c)

複製代碼

 1     final boolean uniWhenComplete(CompletableFuture<T> a, BiConsumer<? super T, ? super Throwable> f, UniWhenComplete<T> c) { 2         Object r; 3         T t; 4         Throwable x = null; 5         if (a == null || (r = a.result) == null || f == null) // 被依賴的任務還未完成 6             return false; 7         if (result == null) { // 被依賴的任務完成了 8             try { 9                 if (c != null && !c.claim()) // 判斷任務是否能被執行10                     return false;11                 if (r instanceof AltResult) { // 判斷異常,AltResult類型很簡單,裏面只有一個屬性Throwable ex; 12                     x = ((AltResult) r).ex;13                     t = null;14                 } else {15                     @SuppressWarnings("unchecked")16                     T tr = (T) r; // 正常的結果17                     t = tr;18                 }19                 f.accept(t, x); // 執行任務20                 if (x == null) {21                     internalComplete(r); // 任務的結果設置爲被依賴任務的結果22                     return true;23                 }24             } catch (Throwable ex) {25                 if (x == null)26                     x = ex; // 記錄異常27             }28             completeThrowable(x, r); // 設置異常和結果29         }30         return true;31     }

複製代碼

 

push()

複製代碼

 1     final void push(UniCompletion<?, ?> c) { 2         if (c != null) { 3             while (result == null && !tryPushStack(c)) 4                 lazySetNext(c, null); // 失敗重置c的next域 5         } 6     } 7      8     final boolean tryPushStack(Completion c) { 9         Completion h = stack;10         lazySetNext(c, h);11         return UNSAFE.compareAndSwapObject(this, STACK, h, c);12     }13     14     static void lazySetNext(Completion c, Completion next) {15         UNSAFE.putOrderedObject(c, NEXT, next);16     }

複製代碼

 

UniWhenComplete

複製代碼

 1     static final class UniWhenComplete<T> extends UniCompletion<T, T> { 2         BiConsumer<? super T, ? super Throwable> fn; 3  4         UniWhenComplete(Executor executor, CompletableFuture<T> dep, CompletableFuture<T> src, 5                 BiConsumer<? super T, ? super Throwable> fn) { 6             super(executor, dep, src); 7             this.fn = fn; 8         } 9 10         final CompletableFuture<T> tryFire(int mode) { // 鉤子方法11             CompletableFuture<T> d; // 依賴的任務12             CompletableFuture<T> a; // 被依賴的任務13             if ((d = dep) == null || !d.uniWhenComplete(a = src, fn, mode > 0 ? null : this)) // 如果是異步模式(mode = 1),就不判斷任務是否結束14                 return null; // dep爲空,說明已經調用過了15             dep = null;16             src = null;17             fn = null;18             return d.postFire(a, mode); // 鉤子方法之後的處理19         }20     }

複製代碼

 

postFire(CompletableFuture<?> a, int mode)

複製代碼

 1     final CompletableFuture<T> postFire(CompletableFuture<?> a, int mode) { 2         if (a != null && a.stack != null) { // 被依賴的任務存在,且stack不爲空,先處理它 3             if (mode < 0 || a.result == null) // 如果是嵌套模式(mode = -1), 或者任務的結果爲空,直接清空棧 4                 a.cleanStack(); 5             else 6                 a.postComplete(); // 否則,調用postComplete()方法 7         } 8         if (result != null && stack != null) { // 再處理當前任務 9             if (mode < 0) // 嵌套模式,直接返回自身(樹 -> 鏈表,避免過深的遞歸調用)10                 return this;11             else12                 postComplete(); // 調用postComplete()方法13         }14         return null;15     }

複製代碼

 

 cleanStack()

複製代碼

 1     final void cleanStack() { // 過濾掉已經死掉的結點(Not isLive) 2         for (Completion p = null, q = stack; q != null;) { // q指針從頭節點開始,向右移動,s一直執行q的下一個結點,p要麼爲空,要麼指向遍歷過的最後一個活着的結點,一旦發現q死掉了,就斷開q, 連接p, s 3             Completion s = q.next; 4             if (q.isLive()) { // 還活着,p指向遍歷過的最後一個結點,q向右移動 5                 p = q; 6                 q = s; 7             } else if (p == null) { // 說明第一個結點就是死掉的,cas stack, q指向stack 8                 casStack(q, s); 9                 q = stack;10             } else { // 否則的話,連接p, s11                 p.next = s;12                 if (p.isLive()) // 再次判斷p結點是否還或者(在這期間是否有別的線程改動了)13                     q = s; // 還活着,q繼續向右移動14                 else {15                     p = null; // 過期的值,從新開始16                     q = stack;17                 }18             }19         }20     }

複製代碼

 

 如下圖

1. 第1個結點是無效結點,更新stack,更新指針

2. 第2個結點是有效結點,更新指針

3. 第3個結點是無效結點,更新指針

4. 第4個結點是有效結點,更新指針

 

 

thenApply

複製代碼

 1     public <U> CompletableFuture<U> thenApply(Function<? super T, ? extends U> fn) { 2         return uniApplyStage(null, fn); 3     } 4  5     public <U> CompletableFuture<U> thenApplyAsync(Function<? super T, ? extends U> fn) { 6         return uniApplyStage(asyncPool, fn); 7     } 8  9     private <V> CompletableFuture<V> uniApplyStage(Executor e, Function<? super T, ? extends V> f) {10         if (f == null)11             throw new NullPointerException();12         CompletableFuture<V> d = new CompletableFuture<V>();13         if (e != null || !d.uniApply(this, f, null)) {14             UniApply<T, V> c = new UniApply<T, V>(e, d, this, f);15             push(c);16             c.tryFire(SYNC);17         }18         return d;19     }20 21     final <S> boolean uniApply(CompletableFuture<S> a, Function<? super S, ? extends T> f, UniApply<S, T> c) {22         Object r;23         Throwable x;24         if (a == null || (r = a.result) == null || f == null)25             return false;26         tryComplete: if (result == null) {27             if (r instanceof AltResult) {28                 if ((x = ((AltResult) r).ex) != null) {29                     completeThrowable(x, r); // 有異常,直接跳出30                     break tryComplete;31                 }32                 r = null;33             }34             try {35                 if (c != null && !c.claim())36                     return false;37                 @SuppressWarnings("unchecked")38                 S s = (S) r;39                 completeValue(f.apply(s));40             } catch (Throwable ex) {41                 completeThrowable(ex);42             }43         }44         return true;45     }46 47     static final class UniApply<T, V> extends UniCompletion<T, V> {48         Function<? super T, ? extends V> fn;49 50         UniApply(Executor executor, CompletableFuture<V> dep, CompletableFuture<T> src,51                 Function<? super T, ? extends V> fn) {52             super(executor, dep, src);53             this.fn = fn;54         }55 56         final CompletableFuture<V> tryFire(int mode) {57             CompletableFuture<V> d;58             CompletableFuture<T> a;59             if ((d = dep) == null || !d.uniApply(a = src, fn, mode > 0 ? null : this))60                 return null;61             dep = null;62             src = null;63             fn = null;64             return d.postFire(a, mode);65         }66     }

複製代碼

一樣的套路,thenApply/thenApplyAsync -> uniApplyStage -> uniApply -> tryFire -> postFire

thenAccept

複製代碼

 1     public CompletableFuture<Void> thenAccept(Consumer<? super T> action) { 2         return uniAcceptStage(null, action); 3     } 4  5     public CompletableFuture<Void> thenAcceptAsync(Consumer<? super T> action) { 6         return uniAcceptStage(asyncPool, action); 7     } 8  9     private CompletableFuture<Void> uniAcceptStage(Executor e, Consumer<? super T> f) {10         if (f == null)11             throw new NullPointerException();12         CompletableFuture<Void> d = new CompletableFuture<Void>();13         if (e != null || !d.uniAccept(this, f, null)) {14             UniAccept<T> c = new UniAccept<T>(e, d, this, f);15             push(c);16             c.tryFire(SYNC);17         }18         return d;19     }20 21     final <S> boolean uniAccept(CompletableFuture<S> a, Consumer<? super S> f, UniAccept<S> c) {22         Object r;23         Throwable x;24         if (a == null || (r = a.result) == null || f == null)25             return false;26         tryComplete: if (result == null) {27             if (r instanceof AltResult) {28                 if ((x = ((AltResult) r).ex) != null) {29                     completeThrowable(x, r); // 有異常直接跳出30                     break tryComplete;31                 }32                 r = null;33             }34             try {35                 if (c != null && !c.claim())36                     return false;37                 @SuppressWarnings("unchecked")38                 S s = (S) r;39                 f.accept(s);40                 completeNull();41             } catch (Throwable ex) {42                 completeThrowable(ex);43             }44         }45         return true;46     }47 48     static final class UniAccept<T> extends UniCompletion<T, Void> {49         Consumer<? super T> fn;50 51         UniAccept(Executor executor, CompletableFuture<Void> dep, CompletableFuture<T> src, Consumer<? super T> fn) {52             super(executor, dep, src);53             this.fn = fn;54         }55 56         final CompletableFuture<Void> tryFire(int mode) {57             CompletableFuture<Void> d;58             CompletableFuture<T> a;59             if ((d = dep) == null || !d.uniAccept(a = src, fn, mode > 0 ? null : this))60                 return null;61             dep = null;62             src = null;63             fn = null;64             return d.postFire(a, mode);65         }66     }

複製代碼

thenAccept/thenAcceptAsync -> uniAcceptStage -> uniAccept -> tryFire -> postFire

 

thenRun

 

複製代碼

 1     public CompletableFuture<Void> thenRun(Runnable action) { 2         return uniRunStage(null, action); 3     } 4  5     public CompletableFuture<Void> thenRunAsync(Runnable action) { 6         return uniRunStage(asyncPool, action); 7     } 8  9     private CompletableFuture<Void> uniRunStage(Executor e, Runnable f) {10         if (f == null)11             throw new NullPointerException();12         CompletableFuture<Void> d = new CompletableFuture<Void>();13         if (e != null || !d.uniRun(this, f, null)) {14             UniRun<T> c = new UniRun<T>(e, d, this, f);15             push(c);16             c.tryFire(SYNC);17         }18         return d;19     }20 21     final boolean uniRun(CompletableFuture<?> a, Runnable f, UniRun<?> c) {22         Object r;23         Throwable x;24         if (a == null || (r = a.result) == null || f == null)25             return false;26         if (result == null) {27             if (r instanceof AltResult && (x = ((AltResult) r).ex) != null)28                 completeThrowable(x, r);29             else30                 try {31                     if (c != null && !c.claim())32                         return false;33                     f.run();34                     completeNull();35                 } catch (Throwable ex) {36                     completeThrowable(ex);37                 }38         }39         return true;40     }41 42     static final class UniRun<T> extends UniCompletion<T, Void> {43         Runnable fn;44 45         UniRun(Executor executor, CompletableFuture<Void> dep, CompletableFuture<T> src, Runnable fn) {46             super(executor, dep, src);47             this.fn = fn;48         }49 50         final CompletableFuture<Void> tryFire(int mode) {51             CompletableFuture<Void> d;52             CompletableFuture<T> a;53             if ((d = dep) == null || !d.uniRun(a = src, fn, mode > 0 ? null : this))54                 return null;55             dep = null;56             src = null;57             fn = null;58             return d.postFire(a, mode);59         }60     }

複製代碼

thenRun/thenRunAsync -> uniRunStage -> uniRun -> tryFire -> postFire 

thenAcceptBoth

thenAcceptBoth

複製代碼

    public <U> CompletableFuture<Void> thenAcceptBoth(CompletionStage<? extends U> other,
            BiConsumer<? super T, ? super U> action) {        return biAcceptStage(null, other, action);
    }    public <U> CompletableFuture<Void> thenAcceptBothAsync(CompletionStage<? extends U> other,
            BiConsumer<? super T, ? super U> action) {        return biAcceptStage(asyncPool, other, action);
    }

複製代碼

 

biAcceptStage

複製代碼

    private <U> CompletableFuture<Void> biAcceptStage(Executor e, CompletionStage<U> o,
            BiConsumer<? super T, ? super U> f) {
        CompletableFuture<U> b;        if (f == null || (b = o.toCompletableFuture()) == null)            throw new NullPointerException();
        CompletableFuture<Void> d = new CompletableFuture<Void>();        if (e != null || !d.biAccept(this, b, f, null)) {
            BiAccept<T, U> c = new BiAccept<T, U>(e, d, this, b, f);
            bipush(b, c);
            c.tryFire(SYNC);
        }        return d;
    }

複製代碼

 

bipush

複製代碼

 1     final void bipush(CompletableFuture<?> b, BiCompletion<?, ?, ?> c) { 2         if (c != null) { 3             Object r; 4             while ((r = result) == null && !tryPushStack(c)) // a的result還沒準備好,c壓入棧 5                 lazySetNext(c, null); // 失敗重置c的next域 6             if (b != null && b != this && b.result == null) { // b的result也還沒準備好 7                 Completion q = (r != null) ? c : new CoCompletion(c); // 根據a的result決定是否構建CoCompletion, 如果a未結束,則構建一個CoCompletion, CoCompletion最後調用的也是BiCompletion的tryFire 8                 while (b.result == null && !b.tryPushStack(q)) // 將q壓入棧 9                     lazySetNext(q, null); // 失敗重置q的next域10             }11         }12     }

複製代碼

 

CoCompletion

複製代碼

 1     static final class CoCompletion extends Completion { 2         BiCompletion<?, ?, ?> base; 3  4         CoCompletion(BiCompletion<?, ?, ?> base) { 5             this.base = base; 6         } 7  8         final CompletableFuture<?> tryFire(int mode) { 9             BiCompletion<?, ?, ?> c;10             CompletableFuture<?> d;11             if ((c = base) == null || (d = c.tryFire(mode)) == null) // 調用的還是BiCompletion的tryFire方法12                 return null;13             base = null;14             return d;15         }16 17         final boolean isLive() {18             BiCompletion<?, ?, ?> c;19             return (c = base) != null && c.dep != null;20         }21     }

複製代碼

 

biAccept

複製代碼

 1     final <R, S> boolean biAccept(CompletableFuture<R> a, CompletableFuture<S> b, BiConsumer<? super R, ? super S> f, 2             BiAccept<R, S> c) { 3         Object r, s; 4         Throwable x; 5         if (a == null || (r = a.result) == null || b == null || (s = b.result) == null || f == null) 6             return false; // a和b都完成了,纔會往下走 7         tryComplete: if (result == null) { 8             if (r instanceof AltResult) { 9                 if ((x = ((AltResult) r).ex) != null) { // a的異常檢查10                     completeThrowable(x, r);11                     break tryComplete;12                 }13                 r = null;14             }15             if (s instanceof AltResult) {16                 if ((x = ((AltResult) s).ex) != null) { // b的異常檢查17                     completeThrowable(x, s);18                     break tryComplete;19                 }20                 s = null;21             }22             try {23                 if (c != null && !c.claim())24                     return false;25                 @SuppressWarnings("unchecked")26                 R rr = (R) r;27                 @SuppressWarnings("unchecked")28                 S ss = (S) s;29                 f.accept(rr, ss); // 執行任務30                 completeNull();31             } catch (Throwable ex) {32                 completeThrowable(ex);33             }34         }35         return true;36     }

複製代碼

 

BiAccept

複製代碼

 1     static final class BiAccept<T, U> extends BiCompletion<T, U, Void> { 2         BiConsumer<? super T, ? super U> fn; 3  4         BiAccept(Executor executor, CompletableFuture<Void> dep, CompletableFuture<T> src, CompletableFuture<U> snd, 5                 BiConsumer<? super T, ? super U> fn) { 6             super(executor, dep, src, snd); 7             this.fn = fn; 8         } 9 10         final CompletableFuture<Void> tryFire(int mode) {11             CompletableFuture<Void> d;12             CompletableFuture<T> a;13             CompletableFuture<U> b;14             if ((d = dep) == null || !d.biAccept(a = src, b = snd, fn, mode > 0 ? null : this))15                 return null;16             dep = null;17             src = null;18             snd = null;19             fn = null;20             return d.postFire(a, b, mode);21         }22     }23 24     abstract static class BiCompletion<T, U, V> extends UniCompletion<T, V> {25         CompletableFuture<U> snd; // second source for action26 27         BiCompletion(Executor executor, CompletableFuture<V> dep, CompletableFuture<T> src, CompletableFuture<U> snd) {28             super(executor, dep, src);29             this.snd = snd;30         }31     }

複製代碼

 thenAcceptBoth/thenAcceptBothAsync -> biAcceptStage -> biAccept -> tryFire -> postFire

 

acceptEither

複製代碼

 1     public CompletableFuture<Void> acceptEither(CompletionStage<? extends T> other, Consumer<? super T> action) { 2         return orAcceptStage(null, other, action); 3     } 4  5     public CompletableFuture<Void> acceptEitherAsync(CompletionStage<? extends T> other, Consumer<? super T> action) { 6         return orAcceptStage(asyncPool, other, action); 7     } 8  9     private <U extends T> CompletableFuture<Void> orAcceptStage(Executor e, CompletionStage<U> o,10             Consumer<? super T> f) {11         CompletableFuture<U> b;12         if (f == null || (b = o.toCompletableFuture()) == null)13             throw new NullPointerException();14         CompletableFuture<Void> d = new CompletableFuture<Void>();15         if (e != null || !d.orAccept(this, b, f, null)) {16             OrAccept<T, U> c = new OrAccept<T, U>(e, d, this, b, f);17             orpush(b, c);18             c.tryFire(SYNC);19         }20         return d;21     }22 23     final <R, S extends R> boolean orAccept(CompletableFuture<R> a, CompletableFuture<S> b, Consumer<? super R> f,24             OrAccept<R, S> c) {25         Object r;26         Throwable x;27         if (a == null || b == null || ((r = a.result) == null && (r = b.result) == null) || f == null)28             return false; // a和b有一個完成了就往下走29         tryComplete: if (result == null) {30             try {31                 if (c != null && !c.claim())32                     return false;33                 if (r instanceof AltResult) { // 異常34                     if ((x = ((AltResult) r).ex) != null) {35                         completeThrowable(x, r);36                         break tryComplete;37                     }38                     r = null;39                 }40                 @SuppressWarnings("unchecked")41                 R rr = (R) r;42                 f.accept(rr); // 執行43                 completeNull();44             } catch (Throwable ex) {45                 completeThrowable(ex);46             }47         }48         return true;49     }50 51     static final class OrAccept<T, U extends T> extends BiCompletion<T, U, Void> {52         Consumer<? super T> fn;53 54         OrAccept(Executor executor, CompletableFuture<Void> dep, CompletableFuture<T> src, CompletableFuture<U> snd,55                 Consumer<? super T> fn) {56             super(executor, dep, src, snd);57             this.fn = fn;58         }59 60         final CompletableFuture<Void> tryFire(int mode) {61             CompletableFuture<Void> d;62             CompletableFuture<T> a;63             CompletableFuture<U> b;64             if ((d = dep) == null || !d.orAccept(a = src, b = snd, fn, mode > 0 ? null : this))65                 return null;66             dep = null;67             src = null;68             snd = null;69             fn = null;70             return d.postFire(a, b, mode);71         }72     }73 74     final void orpush(CompletableFuture<?> b, BiCompletion<?, ?, ?> c) {75         if (c != null) {76             while ((b == null || b.result == null) && result == null) { // a和b的result都沒好,纔會考慮入棧77                 if (tryPushStack(c)) { // 先入a的棧78                     if (b != null && b != this && b.result == null) { // 入a的棧成功,b的result還沒好79                         Completion q = new CoCompletion(c); // a還未結束,用c構建CoCompletion80                         while (result == null && b.result == null && !b.tryPushStack(q)) // 再次判斷,a和b的result都沒好,纔會考慮入棧81                             lazySetNext(q, null); // 失敗置空q的next域82                     }83                     break;84                 }85                 lazySetNext(c, null); // 失敗置空c的next域86             }87         }88     }

複製代碼

acceptEither/acceptEitherAsync -> orAcceptStage -> orAccept -> tryFire -> postFire

 

allOf

複製代碼

 1     public static CompletableFuture<Void> allOf(CompletableFuture<?>... cfs) { 2         return andTree(cfs, 0, cfs.length - 1); 3     } 4  5     static CompletableFuture<Void> andTree(CompletableFuture<?>[] cfs, int lo, int hi) { // 將一個數組構建成一棵樹,二叉樹,動態規劃 6         CompletableFuture<Void> d = new CompletableFuture<Void>(); 7         if (lo > hi) // empty 8             d.result = NIL; 9         else {10             CompletableFuture<?> a, b;11             int mid = (lo + hi) >>> 1;12             if ((a = (lo == mid ? cfs[lo] : andTree(cfs, lo, mid))) == null13                     || (b = (lo == hi ? a : (hi == mid + 1) ? cfs[hi] : andTree(cfs, mid + 1, hi))) == null)14                 throw new NullPointerException();15             if (!d.biRelay(a, b)) {16                 BiRelay<?, ?> c = new BiRelay<>(d, a, b);17                 a.bipush(b, c); // both18                 c.tryFire(SYNC);19             }20         }21         return d;22     }23 24     static final class BiRelay<T, U> extends BiCompletion<T, U, Void> { // for And25         BiRelay(CompletableFuture<Void> dep, CompletableFuture<T> src, CompletableFuture<U> snd) {26             super(null, dep, src, snd);27         }28 29         final CompletableFuture<Void> tryFire(int mode) {30             CompletableFuture<Void> d;31             CompletableFuture<T> a;32             CompletableFuture<U> b;33             if ((d = dep) == null || !d.biRelay(a = src, b = snd))34                 return null;35             src = null;36             snd = null;37             dep = null;38             return d.postFire(a, b, mode);39         }40     }41 42     boolean biRelay(CompletableFuture<?> a, CompletableFuture<?> b) {43         Object r, s;44         Throwable x;45         if (a == null || (r = a.result) == null || b == null || (s = b.result) == null)46             return false; // a和b都結束了才往下執行47         if (result == null) {48             if (r instanceof AltResult && (x = ((AltResult) r).ex) != null)49                 completeThrowable(x, r);50             else if (s instanceof AltResult && (x = ((AltResult) s).ex) != null)51                 completeThrowable(x, s);52             else53                 completeNull(); // 輔助結點,什麼都不做54         }55         return true;56     }

複製代碼

allOf -> andTree -> biRelay -> tryFire -> postFire

 

anyOf

複製代碼

 1     public static CompletableFuture<Object> anyOf(CompletableFuture<?>... cfs) { 2         return orTree(cfs, 0, cfs.length - 1); 3     } 4  5     static CompletableFuture<Object> orTree(CompletableFuture<?>[] cfs, int lo, int hi) { // 將一個數組構建成一棵樹,二叉樹,動態規劃 6         CompletableFuture<Object> d = new CompletableFuture<Object>(); 7         if (lo <= hi) { 8             CompletableFuture<?> a, b; 9             int mid = (lo + hi) >>> 1;10             if ((a = (lo == mid ? cfs[lo] : orTree(cfs, lo, mid))) == null11                     || (b = (lo == hi ? a : (hi == mid + 1) ? cfs[hi] : orTree(cfs, mid + 1, hi))) == null)12                 throw new NullPointerException();13             if (!d.orRelay(a, b)) {14                 OrRelay<?, ?> c = new OrRelay<>(d, a, b);15                 a.orpush(b, c);16                 c.tryFire(SYNC);17             }18         }19         return d;20     }21 22     static final class OrRelay<T, U> extends BiCompletion<T, U, Object> { // for Or23         OrRelay(CompletableFuture<Object> dep, CompletableFuture<T> src, CompletableFuture<U> snd) {24             super(null, dep, src, snd);25         }26 27         final CompletableFuture<Object> tryFire(int mode) {28             CompletableFuture<Object> d;29             CompletableFuture<T> a;30             CompletableFuture<U> b;31             if ((d = dep) == null || !d.orRelay(a = src, b = snd))32                 return null;33             src = null;34             snd = null;35             dep = null;36             return d.postFire(a, b, mode);37         }38     }39 40     final boolean orRelay(CompletableFuture<?> a, CompletableFuture<?> b) {41         Object r;42         if (a == null || b == null || ((r = a.result) == null && (r = b.result) == null))43             return false; // a和b有一個結束就往下進行44         if (result == null)45             completeRelay(r);46         return true;47     }

複製代碼

anyOf -> orTree -> orRelay -> tryFire -> postFire

數組構建樹

allOf和anyOf都用到了數組構建成樹的策略。

假設有一個任務Z(虛擬的,什麼都不做),依賴一組任務[A, B, C, D, E, F, G, H]

對於allOf, 當這組任務都完成時,纔會執行Z;對於anyOf, 當這組任務中有任何一個完成,就執行任務Z。

如果這組任務是數組結構或者鏈表結構,我們該如何解決呢?遍歷數組或者是鏈表,當任務都完成或者有一個完成時,就執行Z,需要不停地遍歷,這是輪詢的方法,不合適。

整個基調是回調,是指,當一個任務完成時,會接着執行所有依賴於它的任務。

作爲一個數組或者鏈表,該如何應用回調呢?誰在先,誰在後呢?因爲不知道哪個任務會先完成,所以沒法確定次序。而且這組任務之間也不應該相互依賴,它們只不過都是被Z依賴。

如果這組任務只有一個的話,那就演變成了X.thenXXX(Z), 如果這組任務有兩個的話,allOf -> Both,anyOf -> Either

 

如果Z依賴Z1,Z2兩個個任務,Z1和Z2依賴Z11,Z12和Z21,Z22四個任務,依次類推,當虛擬的任務的個數達到真實任務的個數的一半時,就讓虛擬任務監聽真實的任務,動態規劃加二叉樹,時間複雜度也只是logn級別的。

複製代碼

 1     static String array2Tree(String[] cfs, int lo, int hi) { 2         String d = new String(cfs[lo] + cfs[hi]); 3         if (lo <= hi) { 4             String a, b; 5             int mid = (lo + hi) >>> 1; // 二分 6             if (lo == mid) { // a作爲左半部分的的結果 7                 a = cfs[lo]; // 當只有不超過兩個元素時,a直接取第一個值 8             } else { 9                 a = array2Tree(cfs, lo, mid);10             }11             if (lo == hi) { // 當只有一個元素的時候,b取a的值12                 b = a;13             } else {14                 if (hi == mid + 1) { // 右半部分只有兩個元素時,b取第二個元素的值15                     b = cfs[hi];16                 } else {17                     b = array2Tree(cfs, mid + 1, hi);18                 }19             }20             if (a == null || b == null) {21                 throw new NullPointerException();22             }23             System.out.println("[" + a + "][" + b + "]->[" + d + "]");24         }25         return d;26     }

複製代碼

 

Console

複製代碼

[A][B]->[AB]
[C][D]->[CD]
[AB][CD]->[AD]
[E][F]->[EF]
[G][H]->[GH]
[EF][GH]->[EH]
[AD][EH]->[AH]

複製代碼

 

如下圖

 

對於allOf, Z只要保證Z1和Z2都完成了就行,Z1和Z2分別保證Z11,Z12 和 Z21,Z22都完成了就像,而Z11,Z12,Z21,Z22則分別保證了A-H任務都完成。

對應anyOf, Z 只要保證Z1和Z2有一個完成了就像,Z1和Z2聯合保證了Z11,Z12,Z21,Z22這4個任務只要有一個完成了就行,同理,Z11,Z12,Z21,Z22則聯合保證了A-H中有一個任務完成了就行。

然後,Z就可以執行了,其實Z什麼也沒做,只是從這組任務裏得出一個結果。

 

行文至此結束。

 

尊重他人的勞動,轉載請註明出處:http://www.cnblogs.com/aniao/p/aniao_cf.html



發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章