Как ждать основного потока, пока асинхронные методы не будут завершены sh? - PullRequest
2 голосов
/ 03 апреля 2020

У меня есть Service.class с start() методом:

public void start()  {  
    for (int i = 0; i < companiesList.size(); i++) {
        asychronous.someAsynchronous(...);
    }
    log.info("Start method has finished");
}

У меня Asynchronous.class с someAsynchronous() методом:

@Async("threadPoolTaskExecutor")
public CompletableFuture<Void> someAsynchronous(some_parameters) {
    //do some stuff
    return null;
}

log.info() отображается до завершения someAsynchronous() методов. Как заставить его ждать log.info(), пока someSynchronous() методы в l oop не закончатся sh? Кстати: асинхронные потоки все еще работают после завершения l oop.

1 Ответ

2 голосов
/ 03 апреля 2020

Запросы CompletableFuture<Void> запрашиваются для выполнения, но после того, как все они запускаются в отдельных потоках, for-l oop завершается и журнал печатается даже до того, как завершится любой из них. В этом преимущество асинхронной обработки - вам не важны их результаты и то, сколько времени они потратили на выполнение.

Чтобы достичь желаемого, вы должны периодически проверять, является ли все из них завершаются до того, как вы перейдете к выходу журнала.

// Adds executions to the List
List<CompletableFuture<Void>> futures = new ArrayList<>();
for (int i = 0; i < companiesList.size(); i++) {
    futures.add(asychronous.someAsynchronous(...));
}

// Periodical check
Iterator<CompletableFuture<Void>> iterator = futures.iterator();
while (iterator.hasNext()) {
    CompletableFuture<Void> future = iterator.next(); // get the next one
    if (future.isDone()) {                            // if finished...
        //...                                         // ... do an action
        iterator.remove();                            // ... and remove from the Iterator
    }
    if (!iterator.hasNext()) {                        // if you reach the end
        iterator = futures.iterator();                // ... repeat the remaining Futures
    }
}

log.info("Start method has finished");

Обратите внимание, что этот метод не завершается sh до тех пор, пока все выполнения не будут выполнены.


Редактировать: Спасибо @ Kayaman , который предложил использовать один метод , предназначенный для этого, заменяя целую Iterator логику. futures должен быть массивом:

// Adds executions to the List
List<CompletableFuture<Void>> futures = new ArrayList<>();
for (int i = 0; i < companiesList.size(); i++) {
    futures.add(asychronous.someAsynchronous(...));
}

// Join the completion of all the threads
CompletableFuture.allOf(futures.toArray(new CompletableFuture[0])).join();

log.info("Start method has finished");
...