2011-04-20 82 views
2

我有一個處理特定傳入請求的servlet。我們將其稱爲`UpdateUserStats'。我希望通話速度快,但我也需要請求執行相當昂貴的任務。我認爲如果讓UpdateUserStats servlet執行所有確定成功或失敗的工作,堅持新的狀態,然後爲後臺線程排隊一些工作以便立即處理並返回成功,這可能是一個很好的解決方案。Java,Tomcat,ServletContextListener和後臺線程

這看起來不錯,但我想知道如何處理關機。當服務器關閉時,我想確保它不會殺死後臺線程,直到沒有更多的工作。我正在考慮使用tomcat ServletContextListener來讓後臺線程知道服務器正在關閉,並且一旦隊列結束就退出了,但我不能100%確定這將會如何工作。請求contextDestroyed()只有在所有請求都完成處理後?界面似乎暗示了這一點,但我沒有在文檔中找到它。另外,我不知道Tomcat在生氣之前願意等待多久,後臺線程沒有終止。

或者,有沒有更好的方法來處理這個問題?如果Spring有一些神奇的後請求後臺工作功能,那麼這是一個Spring應用程序。

回答

1

基於Servlet規範文檔

「在應用程序關閉,聽衆以相反的順序通知其申報 與通知會話監聽前述通知上下文監聽。會議的聽衆必須在上下文監聽器 被通知應用程序關閉之前被通知會話失效。「

因此,這應該是第一個處理通知線程完成其工作的偵聽器。

我已經使用了tomcat,並且至今我已經看到,如果偵聽器尚未完成,那麼在放棄執行乾淨關閉之前,它不會等待超過10-15秒。

通常像Spring這樣的所有容器在關機期間使用監聽器進行乾淨的出口

1

提及替代方法,您可以在單獨的JVM中創建隊列(使用ActiveMQ,RabbitMQ或更簡單的東西)。這樣,即使tomcat出現故障,任務也會被處理。

1

您可以使用ThreadPool,並在應用程序範圍內使用最大線程數,然後它將在必要時排隊,並且可以根據硬件和線程任務進行配置。對於需要使用的ExecutorService:http://download.oracle.com/javase/6/docs/api/java/util/concurrent/ExecutorService.html

線程池可以初始化如下

executorPool = Executors.newFixedThreadPool(50);

在你的服務方法中,你可以定義提交給線程如下: executorPool.submit(new ProcessTask());

清理ThreadPool可以在銷燬/關閉(應用程序)期間完成,如下所示: executorPool.shutdownNow();

希望這是很有幫助的