Spring 3.2中使用@Async任务并返回Future类型

23

我正在尝试实现一个返回类型为Future的Spring @Async任务,但我真的无法弄清楚如何正确地执行它。

  1. 这样做会有什么好处?我现在是否可以控制我的任务,以便我可以停止它并运行它?
  2. 是否有任何参考实现可以让我学习如何实现?Spring官方文档中没有提供。

编辑

来自Spring源码和Spring参考手册:

甚至返回值的方法也可以异步调用。但是,这些方法需要具有Future类型的返回值。这仍然提供了异步执行的好处,以便调用者在调用该Future之前执行其他任务。

并且它给出了以下示例:

@Async
Future<String> returnSomething(int i) {
// this will be executed asynchronously
}

如何正确实现这个?

3个回答

29

请查看这篇博客文章.

使用@Async允许您异步运行方法中的计算。这意味着如果在Spring管理的bean上调用它,控制立即返回给调用者,方法中的代码在另一个线程中运行。调用者接收一个绑定到正在运行的计算的Future对象,并可以使用它来检查计算是否正在运行和/或等待结果。

创建这样的方法很简单。如博客文章所示,用@Async注释它并将结果包装在AsyncResult中。


这意味着如果任务尚未被取消,我可以随时停止我的任务,对吗? - engma
3
是的,你可以通过调用返回的Future对象上的cancel(true)方法来中断你的异步方法。但是中断不会自动生效,方法本身需要检查是否被中断,可以通过调用Thread.isInterrupted()或使用抛出InterruptedException的方法来实现。请参阅The Java Tutorial中的Interrupts章节。 - Petr
为什么结果必须被包装在AsyncResult中? - user1860447
因为如果结果是异步计算的,你需要一种查询结果是否准备好的方法,能够等待它(可能带有超时),或者取消异步计算。 - Petr
@PetrPudlák 如果我需要异步执行一个任务,并且需要立即获取一个 taskId(表示任务注册的字符串,帮助用户跟踪任务进度),那么在必须由带有 @Async 注释的方法生成 taskId 而不是调用者时,我该如何实现这一点? - Web User

10

请查看这篇博客文章,其中涉及IT技术相关内容。

重要的配置如下:

  1. 在Spring管理的bean方法上使用@Async注解。
  2. 通过定义以下内容在Spring配置XML中启用异步:
<!-- 
    Enables the detection of @Async and @Scheduled annotations
    on any Spring-managed object.
-->
<task:annotation-driven />

默认情况下,将使用SimpleAsyncTaskExecutor。

将响应封装在Future<>对象中。


示例

@Async
public Future<PublishAndReturnDocumentResult> generateDocument(FooBarBean bean) {  
    // do some logic  
    return new AsyncResult<PublishAndReturnDocumentResult>(result);
}

您可以使用 result.isDone() 来检查结果是否完成,或者等待获取响应 result.get()


2

ExecutorService可以调度Callable并返回Future对象。Future是一个占位符,一旦结果可用,它就会包含结果。它允许您检查结果是否存在、取消任务或阻塞并等待结果。只有在期望从任务中获得某个对象/值时,Future才有用。

正确的Future调用方式是:

Future<Integer> futureEvenNumber = executorService.submit(new NextEvenNumberFinder(10000));

// Do something.

try {
   Integer nextEvenNumber = futureEvenNumber.get();
} catch (ExecutionException e) {
   System.err.println("NextEvenNumberFinder threw exception: " + e.getCause());
}

下一个偶数查找器类:
public class NextEvenNumberFinder implements Callable<Integer> {
private int number;

public NextEvenNumberFinder(int number) { this.number = number; }

@Override
public Integer call() throws Exception {
    for (;;)
        if (isEvenNumber(++number)) return number;
}

Spring Integration参考手册:http://static.springsource.org/spring-integration/reference/htmlsingle/

注:本文档涉及IT技术相关内容。

}


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