2010-02-10 108 views
2

我有一個使用Spring TaskExecutor的Web應用程序。任務執行程序在Web應用程序第一次加載時啓動,並且該線程運行Web應用程序的整個生命週期。自從我將此線程添加到應用程序後,Oracle Application Server將不再正常關閉。我的猜測是,OAS沒有關閉,因爲我沒有正常關閉代碼中任何地方的任務執行程序線程。在哪裏最好的地方是關閉網絡應用程序中的任務執行器?我在Spring 2.5.6上使用Java 5。當Web服務器關閉時,關閉Web應用程序中的TaskExecutor

這裏是我使用的任務執行:

<bean id="taskExecutor" class="org.springframework.core.task.SimpleAsyncTaskExecutor"/> 

回答

0

通常,web應用程序可以通過ServletContextListener對容器關閉作出反應。實施一個並使用它來關閉您的Executor。理想情況下,你應該把它與整個Spring生命週期的正確關閉結合起來。我依稀記得Spring已經爲此目的準備了一些東西,所以在這裏檢查也是一個好主意。

+0

謝謝。 Spring有ApplicationListener接口。任何想法如何我可以取消LinkedBlockingQueue.take()塊?我試過myQueue.notifyAll()。 – 2010-02-12 14:53:58

+0

我的標準答案是「永遠不要在任何地方使用阻止等待」。或者注入一個稱爲「毒丸」的特殊對象或中斷該線程,如http://stackoverflow.com/questions/812342/how-to-interrupt-a-blockingqueue-which-is-blocking-on-take – 2010-02-12 17:07:01

2

SimpleAsyncTaskExecutor沒有有意義的狀態,它不需要正常關閉。另外,我不確定「線程是否運行了Web應用程序的整個生命週期」 - 您指的是哪個線程?

但是,它產生的線程可能會阻止您的服務器關閉。 SimpleAsyncTaskExecutor使用ThreadFactory來創建它的線程,並且默認情況下創建的線程不是守護線程,因此當啓動關閉時仍然執行的任何衍生線程都將繼續,並且服務器將僅在所有這些衍生線程完成。

作爲解決方案,我建議使用ThreadPoolTaskExecutor而不是SimpleAsyncTaskExecutor。它有一個布爾屬性,用於控制發生關閉時發生的情況,並且如果需要,它可以強制終止線程池。

如果你仍然想使用SimpleAsyncTaskExecutor,那麼你可以注入一個自定義ThreadFactory它創建deamon線程。這將允許服務器關閉,無論這些派生線程的狀態如何。但是,如果這些線程可能使資源處於不穩定狀態,這可能會很危險。

Spring提供了bean的友好實施ThreadFactoryCustomizableThreadFactory),你可以注入SimpleAsyncTaskExecutor,在daemon屬性設置爲false

+0

我給這一個鏡頭。我的意思是「線程運行Web應用程序的整個生命週期」是,當加載Spring上下文時,我使用任務執行器來產生一個線程,這是一個消費者。此線程是執行程序創建的唯一線程,它在Web服務器關閉之前一直運行。 – 2010-02-10 13:53:14

+0

啊,那就是問題了 - 那個線程不會等到服務器關閉,服務器會等待*關閉。 – skaffman 2010-02-10 14:49:07

0

可以使用@PreDestroy註釋:

@PreDestroy 
protected void shutDown() { 
    taskExecutor.shutdown(); 
} 
相關問題