2012-10-01 31 views
10

我已經有工作的春天MVC應用程序,接下來我要做的是從我的應用程序啓動或提交後臺任務。從春天mvc應用程序提交背景任務

基本上我想保留任務直到它完成,即使用戶決定在應用程序上做其他事情。

但是如果我需要,我也想停止/終止/暫停任務。因爲在我尋找更好/更好的方式來做到這一點之前,我還沒有做到這一點。

我認爲這是一個非常有用:

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

How do you kill a thread in Java?

Java threads: Is it possible view/pause/kill a particular thread from a different java program running on the same JVM?

所以我想用@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過程不停止,我在這裏失蹤了什麼?

回答

9

使用線程ID太低且易碎。如果您決定使用@Async annotation(不錯的選擇),則可以使用Future<T>來控制任務執行。基本上,你的方法應該返回的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"; 
} 

棘手的部分是以某種方式存儲返回future對象,它可用於隨後的請求。當然,你不能使用字段或ThreadLocal。您可以放入會話中,但請注意Future不可序列化,並且不會跨羣集工作。

由於@Async通常由線程池支持,因此您的任務很可能還沒有開始。取消只會將其從游泳池中移除。如果任務已經運行,則可以通過線程標記isInterrupted()或處理InterruptedException來發現cancel()調用。

+0

+1 for @Async。你可以添加一個鏈接到http:// static。springsource.org/spring/docs/3.0.x/reference/scheduling.html? –

+0

@Tomasz Nurkiewicz你好,謝謝你的回覆。實際包含'fooAsync()'實現的類是否需要實現Runnable?如果我創建了一箇中斷線程執行後臺任務的取消方法,Thread.currentThread()中斷會中斷那個特定的線程嗎?你能舉個例子嗎? –

+0

@DavidGrant:當然,您也可以自由編輯SO上的任何帖子(您已經這麼做了,謝謝)。 –