13

我有工作的 spring 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该过程并没有停止时,我在这里缺少什么?

4

1 回答 1

11

使用线程 ID 级别太低且脆弱。如果您决定使用@Async注解(不错的选择),您可以使用它Future<T>来控制任务执行。基本上你的方法应该返回 aFuture<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";
}

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

由于@Async通常由线程池支持,因此您的任务可能甚至还没有开始。取消只会将其从池中删除。如果任务已经在运行,您可以通过isInterrupted()线程标志或句柄InterruptedException来发现cancel()调用。

于 2012-10-01T09:37:53.630 回答