allOf函数会等待所有的异步任务执行完成之后统一返回结果.anyOf函数会优先返回最先完成的任务结果.
运用:
public class alofDemo01 {
public static void main(String[] args) throws ExecutionException, InterruptedException {
CompletableFuture<String> future = CompletableFuture.supplyAsync(() -> {
try {
System.out.println("我已经执行了");
TimeUnit.SECONDS.sleep(3);
} catch (InterruptedException e) {
e.printStackTrace();
}
return "hello";
});
CompletableFuture<String> future1 = CompletableFuture.supplyAsync(() -> {
try {
TimeUnit.SECONDS.sleep(2);
System.out.println("我已经执行了第二次");
} catch (InterruptedException e) {
e.printStackTrace();
}
return "test";
});
CompletableFuture<Void> allOf = CompletableFuture.allOf(future, future1);
allOf.thenRun(() -> {
try {
String s = future.get();
System.out.println(System.currentTimeMillis() + s);
} catch (InterruptedException e) {
e.printStackTrace();
} catch (ExecutionException e) {
e.printStackTrace();
}
try {
String s = future1.get();
System.out.println(System.currentTimeMillis() + s);
} catch (InterruptedException e) {
e.printStackTrace();
} catch (ExecutionException e) {
e.printStackTrace();
}
});
System.out.println("测试阻塞");
allOf.get();
}
}
执行结果:
除了时间戳以外,我们还可以看到输出日志.可以得出任务是异步执行的.然后主线程会被阻塞在get方法中,等待异步任务的完成.get方法为什么会阻塞,可以参考前面文章.
supplyAsync方法:
可以参考前面文章,有详细讲解.
allOf方法:
/**
* Returns a new CompletableFuture that is completed when all of
* the given CompletableFutures complete. If any of the given
* CompletableFutures complete exceptionally, then the returned
* CompletableFuture also does so, with a CompletionException
* holding this exception as its cause. Otherwise, the results,
* if any, of the given CompletableFutures are not reflected in
* the returned CompletableFuture, but may be obtained by
* inspecting them individually. If no CompletableFutures are
* provided, returns a CompletableFuture completed with the value
* {@code null}.
*
* <p>Among the applications of this method is to await completion
* of a set of independent CompletableFutures before continuing a
* program, as in: {@code CompletableFuture.allOf(c1, c2,
* c3).join();}.
*
* @param cfs the CompletableFutures
* @return a new CompletableFuture that is completed when all of the
* given CompletableFutures complete
* @throws NullPointerException if the array or any of its elements are
* {@code null}
*/
public static CompletableFuture<Void> allOf(CompletableFuture<?>... cfs) {
return andTree(cfs, 0, cfs.length - 1);
}
allOf方法理解:
andTree方法:
/** Recursively constructs a tree of completions. */
static CompletableFuture<Void> andTree(CompletableFuture<?>[] cfs,
int lo, int hi) {
CompletableFuture<Void> d = new CompletableFuture<Void>();
if (lo > hi) // empty
d.result = NIL;
else {
CompletableFuture<?> a, b;
int mid = (lo + hi) >>> 1;
if ((a = (lo == mid ? cfs[lo] :
andTree(cfs, lo, mid))) == null ||
(b = (lo == hi ? a : (hi == mid+1) ? cfs[hi] :
andTree(cfs, mid+1, hi))) == null)
throw new NullPointerException();
if (!d.biRelay(a, b)) {
BiRelay<?,?> c = new BiRelay<>(d, a, b);
a.bipush(b, c);
c.tryFire(SYNC);
}
}
return d;
}
andTree方法理解:
andTree递归理解:
biRelay方法:
boolean biRelay(CompletableFuture<?> a, CompletableFuture<?> b) {
Object r, s; Throwable x;
if (a == null || (r = a.result) == null ||
b == null || (s = b.result) == null)
return false;
if (result == null) {
if (r instanceof AltResult && (x = ((AltResult)r).ex) != null)
completeThrowable(x, r);
else if (s instanceof AltResult && (x = ((AltResult)s).ex) != null)
completeThrowable(x, s);
else
completeNull();
}
return true;
}
biRelay方法理解:
如果上面结果都是空,返回false,就会进入所有任务同时拿到结果的核心处理地方了.下面看如果返回false做的事.
BiRelay构造方法:
留意下传入参数,d就是新创建的异步任务.a从数组取出的第一个任务,b从数组取出的第二个任务.
BiRelay(CompletableFuture<Void> dep,
CompletableFuture<T> src,
CompletableFuture<U> snd) {
super(null, dep, src, snd);
}
可以亲自点一下这个类的实现,最终还是继承了Completion.所以还是前面讲解的链式调用的思路.(我就不贴源码了.可以自己点一下)
异步任务的bipush方法:
/** Pushes completion to this and b unless both done. */
final void bipush(CompletableFuture<?> b, BiCompletion<?,?,?> c) {
if (c != null) {
Object r;
while ((r = result) == null && !tryPushStack(c))
lazySetNext(c, null); // clear on failure
if (b != null && b != this && b.result == null) {
Completion q = (r != null) ? c : new CoCompletion(c);
while (b.result == null && !b.tryPushStack(q))
lazySetNext(q, null); // clear on failure
}
}
}
异步任务的bipush方法理解:
这里还有个需要注意的地方就是lazySetNext(c,null)和lazySetNext(q,null),如果入栈失败就会把他们置为空.
BiRelay的tryFire方法:
final CompletableFuture<Void> tryFire(int mode) {
CompletableFuture<Void> d;
CompletableFuture<T> a;
CompletableFuture<U> b;
if ((d = dep) == null || !d.biRelay(a = src, b = snd))
return null;
src = null; snd = null; dep = null;
return d.postFire(a, b, mode);
}
BiRelay的tryFire方法理解:
下面的postFire方法就是前面链式调用的思路,具体可以参考前面文章.allOf方法该做就就已经完成了.所有的任务最终都会一个异步任务,然后我们通过thenRun来获取结果.
thenRun方法:
public CompletableFuture<Void> thenRun(Runnable action) {
return uniRunStage(null, action);
}
接受了一个Runnable任务.
uniRunStage方法:
private CompletableFuture<Void> uniRunStage(Executor e, Runnable f) {
if (f == null) throw new NullPointerException();
CompletableFuture<Void> d = new CompletableFuture<Void>();
if (e != null || !d.uniRun(this, f, null)) {
UniRun<T> c = new UniRun<T>(e, d, this, f);
push(c);
c.tryFire(SYNC);
}
return d;
}
uniRunStage方法理解:
uniRun方法:
final boolean uniRun(CompletableFuture<?> a, Runnable f, UniRun<?> c) {
Object r; Throwable x;
if (a == null || (r = a.result) == null || f == null)
return false;
if (result == null) {
if (r instanceof AltResult && (x = ((AltResult)r).ex) != null)
completeThrowable(x, r);
else
try {
if (c != null && !c.claim())
return false;
f.run();
completeNull();
} catch (Throwable ex) {
completeThrowable(ex);
}
}
return true;
}
uniRun方法理解:
这就是allOf方法为什么可以同步获取所有结果的原因.
anyOF方法运用:
public class alofDemo01 {
public static void main(String[] args) throws ExecutionException, InterruptedException {
CompletableFuture<String> future = CompletableFuture.supplyAsync(() -> {
try {
System.out.println("我已经执行了");
TimeUnit.SECONDS.sleep(3000);
} catch (InterruptedException e) {
e.printStackTrace();
}
return "hello";
});
CompletableFuture<String> future1 = CompletableFuture.supplyAsync(() -> {
try {
TimeUnit.SECONDS.sleep(2);
System.out.println("我已经执行了第二次");
} catch (InterruptedException e) {
e.printStackTrace();
}
return "test";
});
CompletableFuture<Object> anyOf = CompletableFuture.anyOf(future, future1);
anyOf.handle((s, throwable) -> {
System.out.println(s);
return s;
});
anyOf.get();
}
}
执行结果:
anyOf方法:
/**
* Returns a new CompletableFuture that is completed when any of
* the given CompletableFutures complete, with the same result.
* Otherwise, if it completed exceptionally, the returned
* CompletableFuture also does so, with a CompletionException
* holding this exception as its cause. If no CompletableFutures
* are provided, returns an incomplete CompletableFuture.
*
* @param cfs the CompletableFutures
* @return a new CompletableFuture that is completed with the
* result or exception of any of the given CompletableFutures when
* one completes
* @throws NullPointerException if the array or any of its elements are
* {@code null}
*/
public static CompletableFuture<Object> anyOf(CompletableFuture<?>... cfs) {
return orTree(cfs, 0, cfs.length - 1);
}
orTree方法:
/** Recursively constructs a tree of completions. */
static CompletableFuture<Object> orTree(CompletableFuture<?>[] cfs,
int lo, int hi) {
CompletableFuture<Object> d = new CompletableFuture<Object>();
if (lo <= hi) {
CompletableFuture<?> a, b;
int mid = (lo + hi) >>> 1;
if ((a = (lo == mid ? cfs[lo] :
orTree(cfs, lo, mid))) == null ||
(b = (lo == hi ? a : (hi == mid+1) ? cfs[hi] :
orTree(cfs, mid+1, hi))) == null)
throw new NullPointerException();
if (!d.orRelay(a, b)) {
OrRelay<?,?> c = new OrRelay<>(d, a, b);
a.orpush(b, c);
c.tryFire(SYNC);
}
}
return d;
}
orRelay方法:
final boolean orRelay(CompletableFuture<?> a, CompletableFuture<?> b) {
Object r;
if (a == null || b == null ||
((r = a.result) == null && (r = b.result) == null))
return false;
if (result == null)
completeRelay(r);
return true;
}
orRelay方法理解:
返回false后OrRelay构造方法:
OrRelay(CompletableFuture<Object> dep, CompletableFuture<T> src,
CompletableFuture<U> snd) {
super(null, dep, src, snd);
}
OrRelay的orpush方法:
/** Pushes completion to this and b unless either done. */
final void orpush(CompletableFuture<?> b, BiCompletion<?,?,?> c) {
if (c != null) {
while ((b == null || b.result == null) && result == null) {
if (tryPushStack(c)) {
if (b != null && b != this && b.result == null) {
Completion q = new CoCompletion(c);
while (result == null && b.result == null &&
!b.tryPushStack(q))
lazySetNext(q, null); // clear on failure
}
break;
}
lazySetNext(c, null); // clear on failure
}
}
}
OrRelay的orpush方法理解:
最后就是返回一个异步任务,执行handle方法.
handle方法:
public <U> CompletableFuture<U> handle(
BiFunction<? super T, Throwable, ? extends U> fn) {
return uniHandleStage(null, fn);
}
uniHandleStage方法:
private <V> CompletableFuture<V> uniHandleStage(
Executor e, BiFunction<? super T, Throwable, ? extends V> f) {
if (f == null) throw new NullPointerException();
CompletableFuture<V> d = new CompletableFuture<V>();
if (e != null || !d.uniHandle(this, f, null)) {
UniHandle<T,V> c = new UniHandle<T,V>(e, d, this, f);
push(c);
c.tryFire(SYNC);
}
return d;
}
uniHandleStage方法理解:
uniHandle方法:
final <S> boolean uniHandle(CompletableFuture<S> a,
BiFunction<? super S, Throwable, ? extends T> f,
UniHandle<S,T> c) {
Object r; S s; Throwable x;
if (a == null || (r = a.result) == null || f == null)
return false;
if (result == null) {
try {
if (c != null && !c.claim())
return false;
if (r instanceof AltResult) {
x = ((AltResult)r).ex;
s = null;
} else {
x = null;
@SuppressWarnings("unchecked") S ss = (S) r;
s = ss;
}
completeValue(f.apply(s, x));
} catch (Throwable ex) {
completeThrowable(ex);
}
}
return true;
}
uniHandle方法理解:
uniHandle方法理解:
因为前面有讲过handle方法,所以注释比较粗糙.不懂得可以参考前面文章,
这就是anyOf方法的思路.其实也是链式调用实现的.