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
        implements Runnable, AsynchronousCompletionTask{}
 //一个输入的Completion,含一个source、依赖和线程池,
 这些是用来后面的函数式Completion的基础
 /* ------------- One-input Completions -------------- */
    /** A Completion with a source, dependent, and executor. */
abstract static class UniCompletion extends Completion {}
 //两个输入的Completion,含2个source、依赖和线程池,
 这些是用来后面的函数式Completion的基础
/* ------------- Two-input Completions -------------- */
/** A Completion for an action with two sources */
abstract static class BiCompletion extends UniCompletion {
        CompletableFuture snd; // second source for action;}
//没有输入的Async异步构造方法
/* ------------- Zero-input Async forms -------------- */
static final class AsyncSupply extends ForkJoinTask
            implements Runnable, AsynchronousCompletionTask {}
static final class AsyncRun extends ForkJoinTask
            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);
    }
}

你可能感兴趣的:(Java)