【发布时间】:2014-01-08 16:12:49
【问题描述】:
我正在尝试在 Spring MVC 应用程序中实现一项功能,以启动一项长期运行的工作。该任务将由 Spring Controller 启动。由于可能需要很长时间才能完成(几分钟到一个多小时),@Async 似乎是我正在尝试做的事情的完美候选者。
一个要求是,我想限制每个 id 的异步任务。解释问题陈述。假设我们需要为给定的学生 ID 构建学生报告。控制器将为给定的 id 启动报告工作。在任何给定时间,对于给定的学生 ID,只能运行一份报告。
如果有新请求进来,如果有针对该 id 的报告运行,我们希望取消它并开始新工作(假设新请求将提供最新信息并且旧请求不再相关) .报告任务可以针对不同的 ID 运行(例如,学生 ID 100 和 200 的作业可以运行,但每个 ID 一次只能运行一个任务。即,ID 100 不应该有两个作业)。
这是控制器的外观:
@RequestMapping("/report/{id}")
.. ...
Future<Void> reportFuture = reportService.generate(id)
.....
服务看起来类似于:
@Async
public Future<Void> generate(int id) {
... Do some Long Calculations generate a report
}
那么,我们如何跟踪异步任务,以便我们知道是否有针对给定 id 的作业正在运行,如果有则取消它?
【问题讨论】:
-
您必须将
Future存储在具有相应ID 的共享地图中。如果有新请求针对同一个 id,您可以取消未来。您可能需要使用一些中断机制来实现您的@Async方法。 -
感谢@SotiriosDelimanolis,澄清一下,这正是我问题的重点。存储 Future 的最佳方式是什么?如果我加入会话,它将仅适用于每个用户会话。可能有多个用户。
-
您可以将它放在
ServletContext中,或者创建一个包含它们的映射的单例bean。不过要小心,您不希望出现内存泄漏。 -
感谢@SotiriosDelimanolis,ServletContext 对我来说可能是完美的解决方案,因为它需要在生成报告时暂时保留它。
标签: spring spring-mvc asynchronous