【问题标题】:Spring 3.2 @Async task with return type of Future返回类型为 Future 的 Spring 3.2 @Async 任务
【发布时间】:2013-06-22 11:01:45
【问题描述】:

我正在尝试实现一个返回类型为 Future 的 spring @Async 任务, 但我真的不知道如何正确地做到这一点。

  1. 这样做我能得到什么?我现在可以控制我的任务,以便我可以停止并运行它吗?
  2. 是否有任何关于我如何做到这一点的参考实现? springsource 不提供。

编辑

来自弹簧源和弹簧参考手册:

甚至可以异步调用返回值的方法。但是,需要这样的方法 有一个 Future 类型的返回值。这仍然提供了异步执行的好处,因此 调用者可以在调用该 Future 上的 get() 之前执行其他任务。

它给出了一个这样的例子:

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

如何正确实现?

【问题讨论】:

    标签: java spring asynchronous


    【解决方案1】:

    查看this blog post

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

    创建这样的方法很简单。使用@Async 对其进行注释并将结果包装在AsyncResult 中,如博文所示。

    【讨论】:

    • 所以这意味着我可以随时停止我的任务,如果它还没有被取消对吧?
    • @Developer106 是的,您可以通过在返回的Future 上调用cancel(true)中断您的异步方法。但是中断不会自动工作。该方法应该通过调用Thread.isInterrupted() 来检查中断,或者使用抛出InterruptedException 的方法。请参阅 Java 教程中的 Interrupts
    • 为什么必须将结果包装在 AsyncResult 中?
    • @user1860447 因为如果结果是异步计算的,你需要一种方法来查询结果是否准备好,能够等待它(可能有超时)或取消异步计算。
    • @PetrPudlák 如果我需要异步执行任务并且需要立即获得taskIdString 代表任务的注册,这有助于用户跟踪任务的进度),鉴于taskId 必须在使用@Async 注释的方法中生成,而不是由调用者生成,我该如何实现?
    【解决方案2】:

    看看这个blog post

    重要的配置是:

    1. @Async 在 Spring 托管 bean 方法上。
    2. 通过定义在 Spring config XML 中启用异步:
    <!-- 
        Enables the detection of @Async and @Scheduled annotations
        on any Spring-managed object.
    -->
    <task:annotation-driven />
    

    默认使用SimpleAsyncTaskExecutor。

    将响应包装在 Future&lt;&gt; 对象中。


    示例

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

    然后您可以使用result.isDone() 检查结果是否完成或等待获得响应result.get()

    【讨论】:

      【解决方案3】:

      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());
      }
      

      NextEvenNumberFinder 类:

      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 集成参考手册:http://static.springsource.org/spring-integration/reference/htmlsingle/

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 2020-03-04
        • 1970-01-01
        • 1970-01-01
        • 2021-09-27
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2020-12-05
        相关资源
        最近更新 更多