复习一下旧的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 :实现了 Runnable 和 Future 接口,内含 Callable ,是桥接Callable/Future API和Runnable/Thread API的默认具体类。
Callable使用
使用方式一:与线程池结合, Callable 提交到线程池,返回 Future
Callable<String> task = () -> {} // 有返回值
Future<String> future = executor.submit(task);
使用方式二:使用 FutureTask ,同时继承了 Future 和 Runnable 接口,可以作为任务提交到 Executor ,或者直接扔进 Thread 执行。
FutureTask<String> future = new FutureTask<>(callable); // 只能接收相同泛型的Callable
executor.execute(future);
在 Executor中,通过Submit方法, Callable 和 Runnable被转换成 FutureTask ,然后进一步执行。其中, Callable 直接设置进 FutureTask.callable , Runnable 通过 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
}
}
}