如何在Spring中检查@Async调用是否已完成?

19

我正在使用@Async注解来执行rsync命令的方法。同时有十个线程在调用此方法。我的要求是只有当所有十个线程都完成了rsync命令的执行后,才能执行剩余的代码,但我不知道如何检查是否所有十个线程都已完全执行@Async方法。请告诉我一种检查的方法。


1
将一条记录写入数据库或将一条消息传递到队列中。 - beerbajay
1个回答

51
如果你要返回某个值,你应该将其包装为标准Java SE Future或Spring的AsyncResult,它也实现了Future
类似这样:
@Component
class AsyncTask {
  @Async
  public Future<String> call() throws InterruptedException {
    return new AsyncResult<String>("return value");
  }
}

如果您已经设置了这个,在调用者中您需要执行以下操作:

public void kickOffAsyncTask() throws InterruptedException {
  Future<String> futureResult =  asyncTask.call();

  //do some stuff in parallel

  String result = futureResult.get();
  System.out.println(result);
}

调用futureResult.get()将会阻塞调用线程并等待异步线程完成。

如果你不想永远等待,可以选择使用Future.get(long timeout, TimeUnit unit)

编辑:

如果你不需要返回任何值,我仍然建议考虑返回虚拟返回值。你不需要将其用于任何事情,只需用它表示特定线程已完成。类似这样:

public void kickOffAsyncTasks(int execCount) throws InterruptedException {
  Collection<Future<String>> results = new ArrayList<>(execCount);

  //kick off all threads
  for (int idx = 0; idx < execCount; idx++) {
    results.add(asyncTask.call());
  }

  // wait for all threads
  results.forEach(result -> {
    try {
      result.get();
    } catch (InterruptedException | ExecutionException e) {
      //handle thread error
    }
  });

  //all threads finished
}

我没有返回任何值,我所做的是运行一个循环来处理150个文件夹(每次循环迭代一个文件夹),使用@Async命令和rsync命令同步数据。我的要求是在所有150个文件夹完成rsync后需要解析文件夹中的数据。 - DnA
3
我想提一下,如果你使用了CompletableFuture,那么你的// wait for all threads代码块可以被CompletableFuture.allOf(results).join()替换。 - Adam Hosman

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接