从春季 mvc 应用提交后台任务

2022-09-04 21:58:16

我有工作春季MVC应用程序,我接下来要做的是从我的应用程序启动或提交后台任务。

基本上,即使用户决定在应用程序上执行其他操作,我也希望保持任务继续进行,直到它完成。

但是,如果需要,我也想停止/杀死/暂停任务。由于我之前还没有这样做,我正在寻找一种好/更好的方法来做到这一点。

我发现这些很有用:

http://blog.springsource.com/2010/01/05/task-scheduling-simplifications-in-spring-3-0/

如何在Java中杀死线程?

Java线程:是否有可能从在同一JVM上运行的不同Java程序中查看/暂停/杀死特定线程?

所以我想使用@Async任务来提交我的后台任务,但想使用线程的ID稍后获取它并在需要时停止它?

这是正确的方法吗?我没有任何多线程的经验,所以我在这里听。

代码更新 :

public interface Worker {
    public void work();
    public void cancel();
}

实现:

@Component("asyncWorker")
public class AsyncWorker implements Worker {

    @Async
    public void work() {
        String threadName = Thread.currentThread().getName();
        System.out.println("   " + threadName + " beginning work");
        try {
                Thread.sleep(10000); // simulates work
        } catch (InterruptedException e) {
            System.out.println("I stopped");
        }
        System.out.println("   " + threadName + " completed work");
    }

    public void cancel() { Thread.currentThread().interrupt(); }
}

用于测试目的的控制器:

@ResponseBody
@RequestMapping("/job/start")
public String start() {
    asyncWorker.work();
    return "start";
}

@ResponseBody
@RequestMapping("/job/stop")
public String stop() {
    asyncWorker.cancel();
    return "stop";
}

当我访问时,我不能同时执行多个任务。另一个仅在第一个完成后才开始执行/job/start

另外,当我访问该过程未停止时,我在这里错过了什么?/job/stop


答案 1

使用螺纹ID的级别太低且易碎。如果您决定使用@Async注释(不错的选择),则可以使用 Future<T> 来控制任务执行。基本上,您的方法应该返回 a 而不是 :Future<T>void

@Async
public Future<Work> work() //...

现在你可以这样做或等待它完成:cancel()Future

@ResponseBody
@RequestMapping("/job/start")
public String start() {
    Future<Work> future = asyncWorker.work();
    //store future somewhere
    return "start";
}

@ResponseBody
@RequestMapping("/job/stop")
public String stop() {
    future.cancel();
    return "stop";
}

棘手的部分是以某种方式存储返回的对象,以便它可用于后续请求。当然,您不能使用字段或 .您可以放入会话,但请注意,这是不可序列化的,并且不能跨群集工作。futureThreadLocalFuture

由于通常由线程池支持,因此您的任务可能甚至尚未启动。取消操作只会将其从池中删除。如果任务已经在运行,则可以对线程标志或句柄进行发现调用。@AsyncisInterrupted()InterruptedExceptioncancel()


答案 2