一:簡介
- 上文提到了Future是實現異步調用的工具,但是Future存在着使用不便的缺點,Java8中提供了CompletableFuture來完善異步流程;
- CompletableFuture能夠在不同線程中執行回調,也可以將回調作爲繼續執行的同步函數,還有在異步的任務完成後,可以通過thenAccept、thenApply、thenCompose等方法繼續執行,而無需阻塞等待下一步執行;
- 下面將通過成員變量、構造方法、控制方法、函數式執行方法來介紹CompletableFuture;
二:成員變量
- 成員變量(關鍵的)
- a).Completion stack,用來保存要執行動作的stack,在多線程等待的時候使用,單線程裏面沒有元素;
- b).Object result ,用來保存執行的結果,或者是封裝的AltResult(可能是異常);
- c).asyncPool,執行任務的線程池,若允許使用的線程併發數大於1,則使用ForkJoinPool;
volatile Object result;// Either the result or boxed AltResult,結果或是封裝的AltResult
volatile Completion stack;// Top of Treiber stack of dependent actions,Treiber Stack Algorithm是一個可擴展的無鎖棧
private static final boolean useCommonPool =
(ForkJoinPool.getCommonPoolParallelism() > 1);
private static final Executor asyncPool = useCommonPool ?
ForkJoinPool.commonPool() : new ThreadPerTaskExecutor();
// Modes for Completion.tryFire. Signedness matters.
static final int SYNC = 0;
static final int ASYNC = 1;
static final int NESTED = -1;
static final AltResult NIL = new AltResult(null);
- 內部類
這些內部類是CompletableFuture執行的基礎,包括對Runnable、Callable封裝的AsyncSupply和AsyncRun,函數式執行的UniCompletion和BiCompletion,還包括異常的封裝類AltResult;
- a.運行相關
//結果內部類的接口
public static interface AsynchronousCompletionTask {}
//基本的執行類和操作
/* ------------- Base Completion classes and operations -------------- */
abstract static class Completion extends ForkJoinTask<Void>
implements Runnable, AsynchronousCompletionTask{}
//一個輸入的Completion,含一個source、依賴和線程池,
這些是用來後面的函數式Completion的基礎
/* ------------- One-input Completions -------------- */
/** A Completion with a source, dependent, and executor. */
abstract static class UniCompletion<T,V> extends Completion {}
//兩個輸入的Completion,含2個source、依賴和線程池,
這些是用來後面的函數式Completion的基礎
/* ------------- Two-input Completions -------------- */
/** A Completion for an action with two sources */
abstract static class BiCompletion<T,U,V> extends UniCompletion<T,V> {
CompletableFuture<U> snd; // second source for action;}
//沒有輸入的Async異步構造方法
/* ------------- Zero-input Async forms -------------- */
static final class AsyncSupply<T> extends ForkJoinTask<Void>
implements Runnable, AsynchronousCompletionTask {}
static final class AsyncRun extends ForkJoinTask<Void>
implements Runnable, AsynchronousCompletionTask {}
/* ------------- Signallers -------------- */
/*記錄和釋放一個阻塞的線程的Completion,它實現了ManagedBlocker來避免
當阻塞動作在ForkJoinPool堆積起來之後飢餓的情況
static final class Signaller extends Completion implements ForkJoinPool.ManagedBlocker {}
- b.單線程執行類,和ForkJoinPool相對
static final class ThreadPerTaskExecutor implements Executor {
public void execute(Runnable r) { new Thread(r).start(); }
}
- c. AltResult:結果相關
//內部封裝了異常
static final class AltResult { // See above
final Throwable ex; // null only for NIL
AltResult(Throwable x) { this.ex = x; }
}
- d.Signaller類,這是CompletableFuture的多線程協作和函數式的很關鍵的一個類,它是繼承自ForkJoinPool的內嵌類ManagedBlocker,它的功能主要有2個:
一是控制ForkJoinPool的common線程池不被阻塞性進程拉低性能,因爲common線程池是整個JVM進程共享的;
二是可以讓不使用ForkJoinPool的common線程池的線程循環等待結果執行完成;
static final class Signaller extends Completion
implements ForkJoinPool.ManagedBlocker {
long nanos; // wait time if timed,超時時間
final long deadline; // non-zero if timed,超時截止時間
// > 0: interruptible 可中斷, < 0: interrupted已中斷
volatile int interruptControl;
volatile Thread thread; //執行的線程
Signaller(boolean interruptible, long nanos, long deadline) {
//執行的線程設置爲當前線程,這個線程一般是指調用get()獲取結果,或者依賴結果的線程
this.thread = Thread.currentThread();
this.interruptControl = interruptible ? 1 : 0;
this.nanos = nanos;
this.deadline = deadline;
}
final CompletableFuture<?> tryFire(int ignore) {
Thread w; // no need to atomically claim
if ((w = thread) != null) {
thread = null;
LockSupport.unpark(w);
}
return null;
}
public boolean isReleasable() {
if (thread == null)
return true;
if (Thread.interrupted()) {
int i = interruptControl;
interruptControl = -1;
if (i > 0)
return true;
}
if (deadline != 0L &&
(nanos <= 0L || (nanos = deadline - System.nanoTime()) <= 0L)) {
thread = null;
return true;
}
return false;
}
public boolean block() {
if (isReleasable())
return true;
else if (deadline == 0L)
LockSupport.park(this);
else if (nanos > 0L)
LockSupport.parkNanos(this, nanos);
return isReleasable();
}
final boolean isLive() { return thread != null; }
}
- 2.CAS的實現
a.UnSafe
在CompletableFuture中使用UnSafe來對其執行結果進行操作,具體的變量分爲:Result、Stack、next,分別是獲取CompletableFuture對象這三個成員變量對應的Offset,然後執行UnSafe的CAS方法,進行同步設置變量,當然讀取變量的時候,是使用直接的方式;
// Unsafe mechanics
private static final sun.misc.Unsafe UNSAFE;
private static final long RESULT;
private static final long STACK;
private static final long NEXT;
static {
try {
final sun.misc.Unsafe u;
UNSAFE = u = sun.misc.Unsafe.getUnsafe();
Class<?> k = CompletableFuture.class;
RESULT = u.objectFieldOffset(k.getDeclaredField("result"));
STACK = u.objectFieldOffset(k.getDeclaredField("stack"));
NEXT = u.objectFieldOffset
(Completion.class.getDeclaredField("next"));
} catch (Exception x) {
throw new Error(x);
}
}