我想知道allOf
的CompletableFuture
方法是否进行轮询或进入等待状态,直到传递给该方法的所有CompletableFutures
完成执行。
我查看了allOf
中IntelliJ
方法的代码,它正在执行某种二进制搜索。
请帮助我找出allOf
的CompletableFuture
方法的实际作用。
public static CompletableFuture<Void> allOf(CompletableFuture<?>... cfs) {
return andTree(cfs, 0, cfs.length - 1);
}
/** 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;
}
/** 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
}
}
}
final CompletableFuture<V> tryFire(int mode) {
CompletableFuture<V> d;
CompletableFuture<T> a;
CompletableFuture<U> b;
if ((d = dep) == null ||
!d.orApply(a = src, b = snd, fn, mode > 0 ? null : this))
return null;
dep = null; src = null; snd = null; fn = null;
return d.postFire(a, b, mode);
}
最佳答案
它不进行二进制搜索-它正在构建一个平衡的二叉树,输入期货位于叶子上,并且内部节点在两个子节点都完成时都完成。
出于某种原因(从代码中看不到),代码作者必须决定将两个期货之间的allOf(_,_)
视为原始操作是最有效的,如果他要求两个以上期货之间的allOf(...)
,则将其制造为这些二进制基元的级联。
这棵树应该保持平衡,以便无论最后完成的 future 是什么,在高层的 future 都可以完成之前,只有少量的层次要崩溃。这可以提高某些情况下的性能,因为它可以确保在我们完全完成工作之前,在某个情况下(如果幸运的话)CPU可能只是闲置,等待异步操作,从而可以处理尽可能多的工作。完成。
通过使最顶部的内部节点在其左子节点下与在其右子节点下的叶子数量一样多来平衡树-这样,两个子节点都将获得原始数组的大约一半,然后代码从树的每一半中递归构建树数组。分成两半看起来有点像二进制搜索的索引计算。
基本结构被似乎设计用于
当某些原始期货已经完成时,
allOf(_)
的结果将返回新的CompleteableFuture
。在大多数情况下,返回单个元素是可行的,但是作者必须要确保该库的用户可以使用新鲜的对象(如果他们将它们用作哈希映射或其他依赖于逻辑的键)关于能够分辨输入的输出以及throw new NullPointerException();
和内联分配(而不是诚实的?:
语句)只有一个if
。这可能会产生较小的字节码,但会降低可读性。除非您亲自支付所得字节码的存储成本,否则不建议将其推荐为一种学习风格。