Java线程和Future API、CompletableFuture

213 阅读4分钟

复习一下旧的Thread & Runnable API的使用。

Thread线程的两种用法

  • 实例化一个 Runnable 对象传入 target
  • 重写 run() 方法

未重写的 run() 方法实际上调用了 this.target 的同名方法。

@Override
public void run() {
    if (target != null) {
        target.run(); // new Thread(Runnable target)
    }
}

Callable/Future API

其主要包含:

Callable 接口:可返回结果、可抛出异常的任务。 Callable 不能直接用于创建线程,要转成 Runnable

Future :计算结果存根。

FutureTask :实现了 RunnableFuture 接口,内含 Callable ,是桥接Callable/Future API和Runnable/Thread API的默认具体类。

Callable使用

使用方式一:与线程池结合, Callable 提交到线程池,返回 Future

Callable<String> task = () -> {} // 有返回值
Future<String> future = executor.submit(task);

使用方式二:使用 FutureTask ,同时继承了 FutureRunnable 接口,可以作为任务提交到 Executor ,或者直接扔进 Thread 执行。

FutureTask<String> future = new FutureTask<>(callable); // 只能接收相同泛型的Callable
executor.execute(future);

Executor中,通过Submit方法, CallableRunnable被转换成 FutureTask ,然后进一步执行。其中, Callable 直接设置进 FutureTask.callableRunnable 通过 Executors.callable(runnable, result) 转化成 Callable ,再赋值。

说一下这个 Executors.callable(runnable, result) 。这里面实际上初始化的是一个内置的适配器 RunnableAdapter ,其实现了 Callable<T> 接口, call() 方法调用 runnable.run() ,再返回 result

所以 Callable 的两种使用方式其实是统一的。这两组API就是这样连接起来。

CompletableFuture的改进

更加先进的异步处理API,支持链式调用、组合多个异步任务、异常处理等。

API描述
runAsync运行无返回值的异步任务
supplyAsync运行有返回值的异步任务
thenApply对结果进行转换,返回一个新的CompletableFuture
thenAccept消费结果
thenRun运行新任务
thenCompose顺序组合
thenCombine合并结果
exceptionally处理计算过程中抛出的异常
allOf等待全部任务完成
anyOf等待任一任务完成

机制详解

使用 VarHandle 对实例属性进行原子操作。 VarHandle 机制见另篇。

// VarHandle mechanics
private static final VarHandle RESULT;
private static final VarHandle STACK;
private static final VarHandle NEXT;
static {
    try {
        MethodHandles.Lookup l = MethodHandles.lookup();
        RESULT = l.findVarHandle(CompletableFuture.class, "result", Object.class);
        STACK = l.findVarHandle(CompletableFuture.class, "stack", Completion.class);
        NEXT = l.findVarHandle(Completion.class, "next", Completion.class);
    } catch (ReflectiveOperationException e) {
        throw new ExceptionInInitializerError(e);
    }
​
    // Reduce the risk of rare disastrous classloading in first call to
    // LockSupport.park: https://bugs.openjdk.java.net/browse/JDK-8074773
    Class<?> ensureLoaded = LockSupport.class;
}

起点 runAsync()

创建任务实例、提交线程池、返回 CompletableFuture 实例。

static CompletableFuture<Void> asyncRunStage(Executor e, Runnable f) {
    if (f == null) throw new NullPointerException();
    CompletableFuture<Void> d = new CompletableFuture<Void>();
    e.execute(new AsyncRun(d, f));
    return d;
}
    // 任务
    @SuppressWarnings("serial")
    static final class AsyncRun extends ForkJoinTask<Void>
        implements Runnable, AsynchronousCompletionTask {
        CompletableFuture<Void> dep; Runnable fn; // CompletableFuture + Runnable
        AsyncRun(CompletableFuture<Void> dep, Runnable fn) {
            this.dep = dep; this.fn = fn;
        }
​
        public final Void getRawResult() { return null; }
        public final void setRawResult(Void v) {}
        public final boolean exec() { run(); return false; }
​
        public void run() {
            CompletableFuture<Void> d; Runnable f;
            if ((d = dep) != null && (f = fn) != null) {
                dep = null; fn = null;
                if (d.result == null) {
                    try {
                        f.run(); // 运行
                        d.completeNull(); // 设置结果
                    } catch (Throwable ex) {
                        d.completeThrowable(ex); // 设置异常结果
                    }
                }
                d.postComplete(); // 任务结束,通知后续任务
            }
        }
    }

转换结果 thenApply()thenApplyAsync()

public <U> CompletableFuture<U> thenApply(
    Function<? super T,? extends U> fn) {
    return uniApplyStage(null, fn); // null线程池
}
public <U> CompletableFuture<U> thenApplyAsync(
    Function<? super T,? extends U> fn) {
    return uniApplyStage(defaultExecutor(), fn); // 默认线程池ForkJoinPool.commonPool()
}
private <V> CompletableFuture<V> uniApplyStage(
    Executor e, Function<? super T,? extends V> f) {
    if (f == null) throw new NullPointerException();
    Object r;
    if ((r = result) != null) // 已有结果
        return uniApplyNow(r, e, f);
    CompletableFuture<V> d = newIncompleteFuture(); // 等待结果
    unipush(new UniApply<T,V>(e, d, this, f));
    return d;
}

已有结果,立即执行分支:

T 是类上泛型,代表前一个 CompletableFuture 的返回结果。 V 是方法签名上泛型,代表即将产生的 CompletableFuture 的返回结果。

private <V> CompletableFuture<V> uniApplyNow(
    Object r, Executor e, Function<? super T,? extends V> f) {
    Throwable x;
    CompletableFuture<V> d = newIncompleteFuture();
    if (r instanceof AltResult) {
        if ((x = ((AltResult)r).ex) != null) {
            d.result = encodeThrowable(x, r);
            return d;
        }
        r = null;
    }
    try {
        if (e != null) {
            e.execute(new UniApply<T,V>(null, d, this, f)); // 异步执行
        } else {
            @SuppressWarnings("unchecked") T t = (T) r;
            d.result = d.encodeValue(f.apply(t)); // 无Executor,同步执行
        }
    } catch (Throwable ex) {
        d.result = encodeThrowable(ex);
    }
    return d;
}

未有结果,加入执行栈等待:

初始化一个 UniApply ,加入执行栈。c:下一任务。

final void unipush(Completion c) {
    if (c != null) {
        while (!tryPushStack(c)) {
            if (result != null) {  // 尝试期间,本任务执行完成
                NEXT.set(c, null); // c.next设置为Null
                break;
            }
        }
        if (result != null)
            c.tryFire(SYNC);
    }
}
final boolean tryPushStack(Completion c) {
    Completion h = stack;
    NEXT.set(c, h);         // CAS piggyback c.next = h
    return STACK.compareAndSet(this, h, c); // VarHandle原子操作等价于this.h = c
}

postComplete() :任务完成通知后续任务。深度优先遍历任务树。

/**
 * Pops and tries to trigger all reachable dependents.  Call only
 * when known to be done.
 */
final void postComplete() {
    /*
     * On each step, variable f holds current dependents to pop
     * and run.  It is extended along only one path at a time,
     * pushing others to avoid unbounded recursion.
     */
    CompletableFuture<?> f = this; Completion h;
    // 条件一:f.stack == null
    // 条件二:f == this || this.stack == null
    // 两者均满足,条件才停止。
    while ((h = f.stack) != null ||
           (f != this && (h = (f = this).stack) != null)) {
        CompletableFuture<?> d; Completion t;
        if (STACK.compareAndSet(f, h, t = h.next)) { // 头结点出栈
            if (t != null) {
                if (f != this) {
                    pushStack(h);
                    continue;
                }
                NEXT.compareAndSet(h, t, null); // try to detach
            }
            f = (d = h.tryFire(NESTED)) == null ? this : d; // 执行,结果赋给d
        }
    }
}