Spring @Async取消并启动?

时间:2014-01-13 05:02:03

标签: spring spring-mvc asynchronous transactions spring-annotations

我有一个spring MVC应用程序,用户可以通过按钮点击启动报告生成。这个过程可能需要几分钟~10-20分钟。 我在服务调用周围使用了spring @Async注释,以便异步发生报告。当我向用户弹出一条消息,表明当前正在运行作业。 现在我想要做的是,如果另一个用户(管理员)可以通过按钮启动报告生成,该按钮应该取消/停止当前运行的@Async任务并重新启动新任务。 为此,我打电话给

.. ..
future = getCurrentTask(id); // returns the current task for given report id
if (!future.isDone())
    future.cancel(true);

service.generateReport(id);

如何使“service.generateReport”在将来取消任务杀死所有正在运行的线程时等待? 根据文档,在我调用future.cancel(true)之后,isDone将返回true,而isCancelled将返回true。所以没有办法知道这份工作真的被取消了。

我只能在取消或完成旧报告时启动新报告生成,以免污染数据。

2 个答案:

答案 0 :(得分:2)

documentation关于cancel()方法,

如果此方法返回true,则后续对isCancelled()的调用将始终返回

试试这个。

future = getCurrentTask(id); // returns the current task for given report id
if (!future.isDone()){
    boolean terminatedImmediately=future.cancel(true);
    if(terminatedImmediately)
        service.generateReport(id);
    else
        //Inform user existing job couldn't be stopped.And to try again  later
}

答案 1 :(得分:0)

假设上面的代码在线程A中运行,并且您最近取消的报告在线程B中运行,那么您需要线程A在service.generateReport(id)之前停止并等待线程B完成/取消。

实现这一目标的一种方法是使用信号量。假设只能同时运行一个报告,首先创建一个所有线程都可访问的信号量对象(通常在报告运行器服务类上)

Semaphore semaphore = new Semaphore(1);

在代码中您需要运行报告的任何位置,请调用acquire()方法。此方法将阻止,直到有许可证可用。同样,当报告执行完成/取消时,请确保调用release()。释放方法将释放许可证并唤醒其他等待线程。

semaphore.acquire();

// run report..

semaphore.release();