2014-01-08 69 views
1

我正試圖在Spring MVC應用程序中實現一個功能,該功能可以啓動長時間運行的作業。該任務將由Spring Controller啓動。由於可能需要很長時間才能完成(幾分鐘到一個多小時),@Async似乎是我嘗試完成的完美人選。Spring MVC @Async限制任務

一個要求是,我想限制每個id的異步任務。解釋問題陳述。假設我們需要爲給定的學生ID建立學生報告。控制器將啓動給定ID的報告工作。在任何給定的時間,只有一個報告可以針對給定的學生ID運行。

如果有新的請求進入,如果有一個報告正在運行該ID,我們想要取消它並開始一個新的工作(假設新的請求將提供最新的信息並且舊的請求不再相關)。報告任務可以針對不同的ID運行(例如,學生ID爲100和200的作業可以運行,但是每個ID只能運行一個任務,即,不應該有兩個ID100的作業)。

這裏是控制器會是什麼樣子:

@RequestMapping("/report/{id}") 
.. ... 
Future<Void> reportFuture = reportService.generate(id) 
..... 

服務將類似於:

@Async 
public Future<Void> generate(int id) { 
... Do some Long Calculations generate a report 
} 

那麼,我們怎樣才能保持跟蹤異步任務,例如,我們知道,如果有是爲給定的ID運行的工作,如果這樣取消的話?

+0

您必須將'Future'存儲在具有相應ID的某個共享地圖中。如果新的請求出現在同一個ID中,您可以取消未來。您可能需要通過一些中斷機制來實現您的'@ Async'方法。 –

+0

謝謝@SotiriosDelimanolis,澄清,這正是我的問題的重點。什麼是最好的方式來存儲未來。如果我進入會話,它將僅適用於每個用戶會話。可能有多個用戶。 – bond

+0

你可以把它放在'ServletContext'中,或者創建一個包含它們映射的單例bean。儘管如此,你不需要內存泄漏。 –

回答

1

我最終通過創建一個可以跟蹤報表的單例作用域組件來解決這個問題。在進行服務呼叫時,它將首先檢查組件以查看給定ID是否有Future。如果不是,則會在該組件中添加Future並開始該過程。如果組件返回Future,它將調用Future上的取消並開始新的服務呼叫。