解決linux下tomcat停止進程任存在問題
在Linux下(之所以強調linux下,是因為在windows下正常),執行tomcat ./shutdown.sh 后,雖然tomcat服務不能正常訪問,但是ps -ef |grep tomcat 后,發現tomcat對應的java進程未隨web容器關閉而銷毀,進而存在僵屍java進程。多次shutdown以后會發現系統內存溢出,然后需要一個一個把tomcat的進程殺掉
問題原因
在Linux系統中當有非守護線程(即User Thread)存在,jvm不會退出(當JVM中所有的線程都是守護線程的時候,JVM就可以退出了;如果還有一個或以上的非守護線程則JVM不會退出)。
在本人項目中是因為使用了ScheduledExecutorService建立了一個定時任務,(executorService會為之維護一個定時服務的線程池,在web容器中建立的線程的生命周期並不會和Web應用程序保持同步,該線程池並不會隨着web容器關閉而銷毀),因此在tomcat停止的時候沒有將這個定時任務線程不會停止。
問題解決
ScheduledExecutorService有一個shutdownNow()方法,只需要在系統停止時調用這個方法將定時任務停掉即可。
另外:
Spring為JDK Timer和Quartz Scheduler所提供的TimerFactoryBean和SchedulerFactoryBean能夠和Spring容器的生命周期關聯,在 Spring容器啟動時啟動調度器,而在Spring容器關閉時,停止調度器。所以在Spring中通過這兩個FactoryBean配置調度器,再從 Spring IoC中獲取調度器引用進行任務調度將不會出現這種Web容器關閉而任務依然運行的問題。