Как мне продолжить CompletableFuture, не дожидаясь вывода

У меня возникла ситуация, когда мне нужно реализовать рекурсию с CompletableFuture. Я хочу вызывать recursionFuture(ex) всякий раз, когда любой из CompletableFuture возвращает какой-либо результат, но я не уверен, как это реализовать. В текущей ситуации recursionFuture(ex) вызывается только тогда, когда оба future1 и future2 возвращают вывод, а затем, если проверяется условие. Любая помощь будет оценена по достоинству.

public static void recursionFuture(ExecutorService ex) 
    {
        try
        {
            CompletableFuture<Object> future1 = CompletableFuture.supplyAsync(() -> new ConcurrencyPoC_CompletableFuture().executeTask(), ex);  
            CompletableFuture<Object> future2 = CompletableFuture.supplyAsync(() -> new ConcurrencyPoC_CompletableFuture().executeTask(), ex);

            if (future1.get() != null | future2.get() != null)
            { 
                System.out.println("Future1: " + future1.get() + " Future2: " + future2.get());
                recursionFuture(ex);
            }
        }
        catch(Exception e)
        {
            e.printStackTrace();
        }
    }

person Pankaj Kumar Katiyar    schedule 24.09.2016    source источник


Ответы (2)


Вы можете комбинировать anyOf() с thenRun() для достижения этого. Просто не вызывайте get() для обоих фьючерсов, потому что это заставляет вашу программу ждать завершения. Вы можете использовать isDone(), чтобы проверить, завершено ли будущее, прежде чем вызывать get().

CompletableFuture<Object> future1 = CompletableFuture.supplyAsync(() -> new ConcurrencyPoC_CompletableFuture().executeTask(), ex);  
CompletableFuture<Object> future2 = CompletableFuture.supplyAsync(() -> new ConcurrencyPoC_CompletableFuture().executeTask(), ex);

CompletableFuture.anyOf(future1, future2).thenRun(() -> {
    if (future1.isDone()) {
        System.out.println("Future 1: " + future1.get());
    }
    if (future2.isDone()) {
        System.out.println("Future 2: " + future2.get());
    }
    recursionFuture(ex);
});

anyOf() создаст новое будущее, которое завершится, как только завершится любое из предоставленных фьючерсов. thenRun() выполнит данное Runnable, как только будет завершено будущее, к которому оно обращается.

person Andrew Lygin    schedule 24.09.2016
comment
Спасибо Андрей, это работает, но есть небольшая проблема. из-за рекурсии код продолжается, даже если executeTask() ничего не возвращает и продолжается до бесконечности. Можно ли поставить проверку на вывод future, например futire1.get() != null, затем вызвать рекурсию, но с ранее заявленной проблемой возникает. Можете ли вы посоветовать здесь, пожалуйста. - person Pankaj Kumar Katiyar; 24.09.2016
comment
Что ж, я получил это, отредактировав код, например: CompletableFuture.anyOf(future1, future2).thenRunAsync(()-› { recursionFuture(ex); } , ex); - person Pankaj Kumar Katiyar; 24.09.2016

Если вы используете только два CompletableFuture, вы также можете взглянуть на runAfterEither / runAfterEitherAsync. Существуют также версии, которые позволяют получить доступ к возвращаемому значению, например acceptEither / acceptEitherAsync.

person user140547    schedule 24.09.2016