2013-01-22 46 views
2

我正在構建一個作爲Spring MVC應用程序實現的插件。這個插件通過一臺服務器上的gui部署在3-6臺tomcat服務器上。插件的每個實例都有一個@Scheduled方法來收集服務器上的信息並將其存儲在中央數據庫中。如何可靠地殺死跨服務器的@ Scheduled線程?

我的問題是,卸載插件的GUI界面留下了一些@Scheduled線程運行。

例如,我有一個服務器1 - 3的環境。我通過服務器1上的gui安裝並啓用插件。現在有3個應用程序在服務器1 - 3上運行@Scheduled線程。如果我回到服務器1和卸載該插件,線程可靠地殺害服務器1個而非服務器2或3

我實現以下,但問題仍然存在:

@Component 
public class ContextClosedListener implements ApplicationListener<ContextClosedEvent> { 
    @Autowired 
    ThreadPoolTaskExecutor executor; 

    @Autowired 
    ThreadPoolTaskScheduler scheduler; 

    public void onApplicationEvent(ContextClosedEvent event) { 
     scheduler.shutdown(); 
     executor.shutdown(); 
    } 
} 

此外,我想過把它作爲一個上下文監聽器而不是@Scheduled方法,但我寧願堅持Spring來進行維護和擴展責任原因。

如何可靠地殺死這樣的環境中的線程?

回答

0

我有一些想法。 ThreadPoolTask​​Executor有一個方法setThreadNamePrefix,它允許你設置線程的前綴。您可以將前綴設置爲唯一的,然後在運行時查找並殺死這些線程。您還可以在同一個對象上使用setThreadGroup方法設置線程組,然後停止線程組中的線程。

更好,更安全的解決方案將是在您的計劃任務中創建分手方法。這是停止一個Thread而不是舊的「在頭部拍攝」調用Thread.stop()的方法的首選方法。您可以通過設置通用前綴或使用上述線程組來獲得對這些Runnable的引用。

接下來的問題是:你如何輕鬆阻止線程?爲此,這將取決於您的應用程序如何實施。由於我主要處理Spring MVC應用程序,因此我的第一個解決方案是編寫一個Controller來處理管理任務。如果這是JBoss或其他一些有JMX的大型應用程序服務器(我可以配置Tomcat來提供JMX,但我認爲它不是以這種方式配置的),我可能會寫一個啓用了JMX的bean允許我通過應用服務器控制檯停止線程。基本上,給自己一個方法來觸發停止線程。