Java的異步編程(三):CompletableFuture的簡介和成員變量

一:簡介

  1. 上文提到了Future是實現異步調用的工具,但是Future存在着使用不便的缺點,Java8中提供了CompletableFuture來完善異步流程;
  2. CompletableFuture能夠在不同線程中執行回調,也可以將回調作爲繼續執行的同步函數,還有在異步的任務完成後,可以通過thenAccept、thenApply、thenCompose等方法繼續執行,而無需阻塞等待下一步執行;
  3. 下面將通過成員變量、構造方法、控制方法、函數式執行方法來介紹CompletableFuture;

二:成員變量

  1. 成員變量(關鍵的)
  • 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);
  1. 內部類
    這些內部類是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; }
    }
  1. 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);
    }
}
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章