¿Por qué el método CompletableFuture allof hacer una búsqueda binaria?

limo_756:

Yo quería saber si el allOfmétodo CompletableFuturehace de votación o entra en un estado de espera hasta que todo el CompletableFuturespasado en el método de completar su ejecución. Miré el código del allOfmétodo IntelliJy lo está haciendo algún tipo de búsqueda binaria.

Por favor, ayudarme a averiguar cuál es el allOfmétodo de la CompletableFutureque realmente hace.

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);
}
hmakholm izquierda sobre Monica:

No hace una búsqueda binaria - es la construcción de un árbol binario balanceado con los futuros de entrada en las hojas, y los nodos internos que cada uno completa cuando sus dos hijos han completado tanto.

Por alguna razón que no es evidente a partir del código, el autor del código debe haber decidido que era más eficiente considerar allOf(_,_)entre exactamente dos futuros a ser su operación primitiva, y si se le pregunta a una allOf(...)entre más de dos futuros, que está fabricarlo como una cascada de estas primitivas binarios.

El árbol debe ser equilibrado para tal de que no importa lo que la última futuro para completar es decir, no sólo será un pequeño número de niveles de izquierda a colapsar antes de que el futuro en la parte superior se puede completar. Esto mejora el rendimiento en algunas situaciones, ya que asegura que tanto trabajo como sea posible puede ser manejado antes de que estamos completamente hecho, en un punto donde (si tenemos suerte) la CPU podría ser simplemente sentados sin hacer nada, esperando que algo asíncrono a completar.

Equilibrar el árbol está hecho por tener la más alta nodo interno tiene casi tantas hojas bajo su hijo izquierdo como derecho en virtud de su hijo - por lo tanto los niños reciben aproximadamente la mitad de la matriz original, y luego el código de forma recursiva construye un árbol de cada mitad del la matriz. La división en dos mitades puede parecer un poco como los cálculos del índice para una búsqueda binaria.


La estructura básica se oscurece ligeramente en casos especiales que parecen estar diseñados para

  • utilizar una ruta de código optimizadas con menos asignaciones cuando algunos de los futuros originales ya se han completado, y
  • asegurarse de que el resultado de allOf(_)exactamente un elemento devolverá un fresco CompleteableFuture . Para la mayoría de los propósitos que funcionaría sólo devolver ese solo elemento, pero el autor debe haber querido garantizar que los usuarios de la biblioteca pueden contar con el objeto de ser fresco, si los están utilizando como claves en los mapas de patata, u otra lógica que depende en ser capaz de decirle a la salida de los insumos y
  • tener un solo throw new NullPointerException();mediante el uso ?:y las asignaciones en línea en lugar de honestos ifdeclaraciones. Esto probablemente produce código de bytes ligeramente más pequeño a expensas de la legibilidad. No puede recomendarse como un estilo de aprender de, a menos que pagar personalmente por el costo de almacenamiento del código de bytes que resulta ...

Supongo que te gusta

Origin http://43.154.161.224:23101/article/api/json?id=229127&siteId=1
Recomendado
Clasificación