一:构造函数和静态工厂方法
1.方法列表
a).CompletableFuture提供了丰富的静态构造方法,从线程类型上支持Runnable、Callable,从线程池上支持自己提供的和默认的;
//构造方法
public CompletableFuture() {}
//针对Callable的异步Future静态工厂方法,使用内部的ForkJoinPool
public static <U> CompletableFuture<U> supplyAsync(Supplier<U> supplier) ;
//针对Callable的异步Future静态工厂方法,使用自定义的Executor
public static <U> CompletableFuture<U> supplyAsync(Supplier<U> supplier, Executor executor) ;
//针对Runnable的异步Future静态工厂方法,使用内部的ForkJoinPool
public static CompletableFuture<Void> runAsync(Runnable runnable);
//针对Runnable的异步Future静态工厂方法,使用内部的ForkJoinPool
public static CompletableFuture<Void> runAsync(Runnable runnable, Executor executor) ;
//直接返回一个值固定的Future,比如在提供默认值的场景下
public static <U> CompletableFuture<U> completedFuture(U value) ;
2.静态工厂方法的内部实现(以supplyAsync为例)
a.supplyAsync静态工厂方法
1.supplyAsync的内部是使用AsyncSupply实现的,会对Future的result赋值,和runAsync的内部是使用AsyncRun内部类实现的,不会对result进行赋值;
2,如下所示,AsyncSupply将Supplier封装成AsyncSupply,然后提交给Executor执行;
public static <U> CompletableFuture<U> supplyAsync(Supplier<U> supplier) {
/*在这里去设置线程池信息,线程池为前文介绍的ForkJoinPool的commonPool,或者是单线程的池子*/
/*所以这里需要注意一下,就是ForkJoinPool的池子,可能被很多地方用*/
return asyncSupplyStage(asyncPool, supplier);
}
static <U> CompletableFuture<U> asyncSupplyStage(Executor e,Supplier<U> f) {
if (f == null) throw new NullPointerException();
CompletableFuture<U> d = new CompletableFuture<U>();
//把Supplier封装成任务,并执行
e.execute(new AsyncSupply<U>(d, f));
return d;
}
3.AsyncSupply中的逻辑为,若当前的result为null,则将Supplier.get()的结果赋值给result,若有异常,则将异常封装为AltResult然后赋值给result;
//AsyncSupply的实现
static final class AsyncSupply<T> extends ForkJoinTask<Void>
implements Runnable, AsynchronousCompletionTask {
CompletableFuture<T> dep; Supplier<T> fn;
AsyncSupply(CompletableFuture<T> dep, Supplier<T> 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 true; }
/*线程的执行函数*/
public void run() {
CompletableFuture<T> d; Supplier<T> f;
if ((d = dep) != null && (f = fn) != null) {
dep = null; fn = null;
if (d.result == null) {
try {
/*同步的执行,获取执行结果*/
d.completeValue(f.get());
} catch (Throwable ex) {
/*出现异常,则将结果设置为异常*/
d.completeThrowable(ex);
}
}
/*完成后,通知依赖项处理*/
d.postComplete();
}
}
}
4.正常和异常的赋值逻辑
//完成时未发生异常,设置其值
/** Completes with a non-exceptional result, unless already completed. */
final boolean completeValue(T t) {
return UNSAFE.compareAndSwapObject(this, RESULT, null,
(t == null) ? NIL : t);
}
//对异常赋值的逻辑
final boolean completeThrowable(Throwable x) {
return UNSAFE.compareAndSwapObject(this, RESULT, null,
encodeThrowable(x));
}
//组装异常
static AltResult encodeThrowable(Throwable x) {
return new AltResult((x instanceof CompletionException) ? x :
new CompletionException(x));
}
二:控制类方法
1.判断是否完成isDone()
如果完成返回true,包括:
//仅仅通过result是否为null来判断,如果已经完成,result会设置值 的
public boolean isDone() {
return result != null;
}
2.获取结果get()、等待结构完成join()
二者的区别很细微,一是在抛出的异常是有些不同,另外是在等待任务结果时,get允许中断,join不允许中断;
它们在等待的时候,都用了自旋的机制,一般自旋256;
public T get() throws InterruptedException, ExecutionException {
Object r;
//如果已经完成,则返回,否则等待结果完成
return reportGet((r = result) == null ? waitingGet(true) : r);
}
public T join() {
Object r;
//如果已经完成,则返回,否则等待结果完成
return reportJoin((r = result) == null ? waitingGet(false) : r);
}
/**
* Returns raw result after waiting, or null if interruptible and interrupted.
在等待后返回运算结果,或者当可被中断、已经中断的情况下,返回null*/
private Object waitingGet(boolean interruptible) {
Signaller q = null;
//标记是否已经进入队列,有且仅进入一次
boolean queued = false;
int spins = -1;
Object r;
//不断循环,直到任务完成
while ((r = result) == null) {
//如果只有一个处理器可用,则进行不断自旋
if (spins < 0)
spins = (Runtime.getRuntime().availableProcessors() > 1) ?
1 << 8 : 0; // Use brief spin-wait on multiprocessors
else if (spins > 0) {
if (ThreadLocalRandom.nextSecondarySeed() >= 0)
--spins;
}
//新建一个signaller,代表当前依赖,并加入队列
else if (q == null)
q = new Signaller(interruptible, 0L, 0L);
else if (!queued)
queued = tryPushStack(q);
//如果允许中断,且已经中断,则将当前线程移出队列,并返回null
else if (interruptible && q.interruptControl < 0) {
q.thread = null;
cleanStack();
return null;
}
//如果当前没被中断,且未完成,则利用managedBlock来管理阻塞,下面会降下这个
else if (q.thread != null && result == null) {
try {
ForkJoinPool.managedBlock(q);
} catch (InterruptedException ie) {
//设置当前进程为已中断
q.interruptControl = -1;
}
}
}
//如果已经完成,根据当前线程是否中断,返回结果
if (q != null) {
q.thread = null;
if (q.interruptControl < 0) {
if (interruptible)
r = null; // report interruption
else
Thread.currentThread().interrupt();
}
}
postComplete();
return r;
}
3.超时获取结果get(long timeout, TimeUnit unit)
它和get()的区别在于:它如果限定时间内,等不到结果,会异常退出
public T get(long timeout, TimeUnit unit)
throws InterruptedException, ExecutionException, TimeoutException {
Object r;
long nanos = unit.toNanos(timeout);
return reportGet((r = result) == null ? timedGet(nanos) : r);
}
//等待
private Object timedGet(long nanos) throws TimeoutException {
//当前线程被中断,直接返回
if (Thread.interrupted())
return null;
if (nanos <= 0L)
throw new TimeoutException();
long d = System.nanoTime() + nanos;
Signaller q = new Signaller(true, nanos, d == 0L ? 1L : d); // avoid 0
boolean queued = false;
Object r;
// We intentionally don't spin here (as waitingGet does) because
// the call to nanoTime() above acts much like a spin.
while ((r = result) == null) {
//入队列
if (!queued)
queued = tryPushStack(q);
//在下面的manageLock中,会对nanos更新,nanos = deadline - System.nanoTime(),
当其小于0,表示超时
else if (q.interruptControl < 0 || q.nanos <= 0L) {
q.thread = null;
cleanStack();
if (q.interruptControl < 0)
return null;
throw new TimeoutException();
}
//管理中断
else if (q.thread != null && result == null) {
try {
ForkJoinPool.managedBlock(q);
} catch (InterruptedException ie) {
q.interruptControl = -1;
}
}
}
if (q.interruptControl < 0)
r = null;
q.thread = null;
postComplete();
return r;
}
4.取消cancel()
用于取消任务,将result设置为cancellationException
public boolean cancel(boolean mayInterruptIfRunning) {
boolean cancelled = (result == null) &&
internalComplete(new AltResult(new CancellationException()));
postComplete();
return cancelled || isCancelled();
}
4.查看取消状态isCancelled()
根据result是否为cancellationException来判断
public boolean isCancelled() {
Object r;
return ((r = result) instanceof AltResult) &&
(((AltResult)r).ex instanceof CancellationException);
}