DeferredResult { public static DeferredResult<?> anyOf(DeferredResult<?>... deferredResults) { CompletableFuture<?>[] cfs = Arrays.stream(deferredResults) .map(d -> d.completableFuture) .collect(Collectors.toList()) .toArray(new CompletableFuture<?>[deferredResults.length]); CompletableFuture<?> cf = CompletableFuture.anyOf(cfs); return new DeferredResult<>(cf); } DeferredResult();  DeferredResult(CompletableFuture<T> completableFuture); static DeferredResult<U> completed(U value); static DeferredResult<U> failed(Throwable ex); static DeferredResult<Void> allOf(DeferredResult<?>... deferredResults); static DeferredResult<List<U>> allOf(List<DeferredResult<U>> deferredResults); static DeferredResult<?> anyOf(DeferredResult<?>... deferredResults); static DeferredResult<U> anyOf(List<DeferredResult<U>> deferredResults); DeferredResult<U> thenApply(Function<? super T, ? extends U> fn); DeferredResult<U> thenApplyAsync(Function<? super T, ? extends U> fn,
            Executor executor); DeferredResult<Void> thenAccept(Consumer<? super T> action); DeferredResult<Void> thenAcceptAsync(Consumer<? super T> action, Executor executor); DeferredResult<Void> thenRun(Runnable action); DeferredResult<Void> thenRunAsync(Runnable action, Executor executor); DeferredResult<V> thenCombine(DeferredResult<? extends U> other,
            BiFunction<? super T, ? super U, ? extends V> fn); DeferredResult<V> thenCombineAsync(DeferredResult<? extends U> other,
            BiFunction<? super T, ? super U, ? extends V> fn, Executor executor); DeferredResult<Void> thenAcceptBoth(DeferredResult<? extends U> other,
            BiConsumer<? super T, ? super U> action); DeferredResult<Void> thenAcceptBothAsync(DeferredResult<? extends U> other,
            BiConsumer<? super T, ? super U> action, Executor executor); DeferredResult<Void> runAfterBoth(DeferredResult<?> other, Runnable action); DeferredResult<Void> runAfterBothAsync(DeferredResult<?> other, Runnable action,
            Executor executor); DeferredResult<U> applyToEither(DeferredResult<? extends T> other,
            Function<? super T, U> fn); DeferredResult<U> applyToEitherAsync(DeferredResult<? extends T> other,
            Function<? super T, U> fn,
            Executor executor); DeferredResult<Void> acceptEither(DeferredResult<? extends T> other,
            Consumer<? super T> action); DeferredResult<Void> acceptEitherAsync(DeferredResult<? extends T> other,
            Consumer<? super T> action,
            Executor executor); DeferredResult<Void> runAfterEither(DeferredResult<?> other, Runnable action); DeferredResult<Void> runAfterEitherAsync(DeferredResult<?> other, Runnable action,
            Executor executor); DeferredResult<U> thenCompose(Function<? super T, ? extends DeferredResult<U>> fn); DeferredResult<U> thenComposeAsync(
            Function<? super T, ? extends DeferredResult<U>> fn,
            Executor executor); DeferredResult<T> exceptionally(Function<Throwable, ? extends T> fn); DeferredResult<T> whenComplete(BiConsumer<? super T, ? super Throwable> action); DeferredResult<T> whenCompleteAsync(BiConsumer<? super T, ? super Throwable> action,
            Executor executor); DeferredResult<U> handle(BiFunction<? super T, Throwable, ? extends U> fn); DeferredResult<U> handleAsync(BiFunction<? super T, Throwable, ? extends U> fn,
            Executor executor); T getNow(T valueIfAbsent); T getNow(Supplier<? extends T> valueSupplierIfAbsent); boolean isDone(); CompletionStage<T> toCompletionStage(); boolean complete(T value); boolean fail(Throwable ex); DeferredResult<T> whenCompleteNotify(Operation operation);  }
@Test public void testAnyOf() throws Throwable { TestContext ctx = new TestContext(1, TestContext.DEFAULT_WAIT_DURATION); int count = 10; List<DeferredResult<Integer>> deferredResults = IntStream.range(0, count) .mapToObj(ignore -> new DeferredResult<Integer>()) .collect(Collectors.toList()); DeferredResult<Integer> deferredResult = DeferredResult.anyOf(deferredResults); deferredResult.whenComplete(ctx.getCompletionDeferred()); int fastest = 7; CountDownLatch latch = new CountDownLatch(1); IntStream.range(0, count).forEach(i -> { if (i == fastest) { runAfter(1, () -> { deferredResults.get(i).complete(i); latch.countDown(); }); } else { runAfter(1, () -> { try { latch.await(); } catch (InterruptedException e) { } deferredResults.get(i).complete(i); }); } }); ctx.await(); Assert.assertEquals(fastest, deferredResult.getNow(exceptionSupplier()).intValue()); }