【问题标题】:Spring MVC @Async limiting taskSpring MVC @Async 限制任务
【发布时间】: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


【解决方案1】:

我最终通过创建一个可以跟踪报告的单例范围组件来解决这个问题。在进行服务调用时,它会首先检查组件以查看给定 id 是否存在Future。如果没有,它将在该组件中添加Future 并启动该过程。如果组件返回Future,它会在Future 上调用取消并开始一个新的服务调用。

【讨论】:

    猜你喜欢
    • 2011-09-12
    • 2015-10-02
    • 2017-03-30
    • 1970-01-01
    • 1970-01-01
    • 2016-05-03
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多