【问题标题】:How to wait for main Thread until asynchronous methods will finish?如何等待主线程直到异步方法完成?
【发布时间】:2020-04-03 20:45:07
【问题描述】:

我有 Service.classstart() 方法:

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

我有 Asynchronous.classsomeAsynchronous() 方法:

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

log.info()someAsynchronous() 方法完成之前出现。 如何强制它等待log.info() 直到循环中的someSynchronous() 方法完成?顺便说一句:完成循环后异步线程仍在运行。

【问题讨论】:

  • 当然之前出现过,这就是异步执行方法的全部意义所在。您确定该方法应该是异步的吗?但是你仍然可以得到CompletableFutures 并等待那些。
  • @Kayaman 它们在新的单独线程中执行,这很好,但我想让它们完成,然后让主线程继续。

标签: java spring spring-boot asynchronous java-8


【解决方案1】:

CompletableFuture&lt;Void&gt; 调用被要求执行,但在它们都在单独的线程中启动之后,for 循环结束并且甚至在它们中的任何一个完成之前打印日志。这就是异步处理的优势——您不必关心它们的结果以及它们执行的时间。

为了实现你想要的,你必须定期检查它们是否所有都完成了,然后再进行日志输出。

// 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");

请注意,在所有执行完成之前,此方法不会结束。


编辑:感谢 @Kayaman,他建议使用单个 method 专用于替换整个 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");

【讨论】:

  • CompletableFuture.allOf(futures).join(); 替换你的迭代器。无需旋转主线程或过度设计迭代器。
  • 谢谢Kayaman,这是一个很好的提示。多线程是我的弱点。
  • 是的,CompletableFuture.allOf(futures.toArray(new CompletableFuture[0]).join();,这是一个可变参数。 @januszj 迭代器可以被替换。或.forEach()if you want.
  • @Kayaman 你的意思是迭代器?迭代器> 迭代器 = CompletableFuture.allOf(futures.toArray(new CompletableFuture[0]).join(); ?
猜你喜欢
  • 2013-08-19
  • 1970-01-01
  • 2013-02-15
  • 1970-01-01
  • 1970-01-01
  • 2015-06-09
  • 1970-01-01
  • 1970-01-01
  • 2019-05-31
相关资源
最近更新 更多