spring-mvc - Spring MVC 的 @Async、DeferredResult 和 Callable 的区别

标签 spring-mvc asynchronous deferred callable

我在 Spring 服务中定义了一个长期运行的任务。它由 Spring MVC Controller 启动。我想启动服务并返回 HttpResponse在服务结束前发送给调用者。该服务最后将文件保存在文件系统上。
在 javascript 中,我创建了一个轮询作业来检查服务状态。

在 Spring 3.2 中,我发现了 @Async注释,但我不明白它与 DeferredResult 有何不同和 Callable .我什么时候必须使用 @Async我什么时候应该使用 DeferredResult ?

最佳答案

异步 注释一个方法,因此它将被异步调用。

@org.springframework.stereotype.Service
public class MyService {
    @org.springframework.scheduling.annotation.Async
    void DoSomeWork(String url) {
        [...]
    }
}

因此 Spring 可以这样做,因此您需要定义将如何执行。例如:
<task:annotation-driven />
<task:executor id="executor" pool-size="5-10" queue-capacity="100"/>

这样,当您调用 service.DoSomeWork("parameter") 时,该调用会被放入要异步调用的执行程序的队列中。这对于可以并发执行的任务很有用。

您可以使用 Async 来执行任何类型的异步任务。如果您想要的是定期调用任务,您可以使用 @预定 (并使用 task:scheduler 而不是 task:executor)。它们是调用 java Runnables 的简化方法。

延迟结果<> 用于在不阻塞用于应答的 Tomcat HTTP 线程的情况下应答请求。通常将是 ResponseBody 注释方法的返回值。
@org.springframework.stereotype.Controller
{
    private final java.util.concurrent.LinkedBlockingQueue<DeferredResult<String>> suspendedRequests = new java.util.concurrent.LinkedBlockingQueue<>();

    @RequestMapping(value = "/getValue")
    @ResponseBody
    DeferredResult<String> getValue() {
            final DeferredResult<String> result = new DeferredResult<>(null, null);
            this.suspendedRequests.add(result);
            result.onCompletion(new Runnable() {
            @Override
            public void run() {
        suspendedRequests.remove(result);
            }
});
            service.setValue(result); // Sets the value!
            return result;
    }
}

前面的示例缺少一件重要的事情,它没有显示将如何设置延迟结果。在其他一些方法(可能是 setValue 方法)中,将会有一个 result.setResult(value)。在调用 setResult 之后,Spring 将调用 onCompletion 过程并将响应返回给 HTTP 请求(参见 https://en.wikipedia.org/wiki/Push_technology#Long_polling)。

但是,如果您只是同步执行 setValue,则使用延迟结果没有任何优势。这就是 Async 的用武之地。您可以使用异步方法在将来的某个时间点使用另一个线程设置返回值。
    @org.springframework.scheduling.annotation.Async
    void SetValue(DeferredResult<String> result) {
        String value;
        // Do some time consuming actions
        [...]
        result.setResult(value);
    }

使用延迟结果不需要异步,它只是一种方法。

在示例中,有一个延迟结果队列,例如,计划任务可能正在监视以处理它的待处理请求。您也可以使用一些非阻塞机制(参见 http://en.wikipedia.org/wiki/New_I/O )来设置返回值。

要完成图片,您可以搜索有关 java 标准 future ( http://docs.oracle.com/javase/1.5.0/docs/api/java/util/concurrent/Future.html ) 和可调用 ( http://docs.oracle.com/javase/1.5.0/docs/api/java/util/concurrent/Callable.html ) 的信息,它们在某种程度上相当于 Spring DeferredResult 和 Async。

关于spring-mvc - Spring MVC 的 @Async、DeferredResult 和 Callable 的区别,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/17855852/

相关文章:

javascript - AngularJS 中的 deferred.resolve()

javascript - jQuery 延迟 :

javascript - 我使用 .done() 不正确,没有按预期返回值

java - Spring 看不到 servlet-context 和 contextConfigLocation bean 之间的 bean

python - 如何为pycharm配置tornado

java - 无法将类型java.lang.String的值转换为所需的类型java.util.Date

c# - 如何使用 linq 进行异步

android - 从系统服务到其他应用程序的异步通信

Spring MVC 上传文件 - 内容类型如何确定?

spring-mvc - hasPermission没有检查字段id怎么办?