tomcat shudown.sh 無法關閉
Tomcat使用shutdown.sh無法關閉Java程序的問題跟蹤
問題:
在伺服器上執行/usr/local/apache-tomcat-7.0.47-3100/bin/shutdown.sh後,使用
ps –aux|grep java 命令檢視,發現java程序還存在,但是服務已經不可用了,即服務沒有完全關閉。
跟蹤過程:
1、 百度查詢“Tomcat無法 shutdown程序”,得出原因為:有非守護執行緒存在的時候,JVM是不會退出的。
2、 查詢shutdown.sh執行之後,有哪些非守護執行緒存在:
操作:1)執行shutdown.sh
2)使用jdk自帶的jstack工具匯出java程序中的執行緒堆疊:
使用ps –aux|grep java檢視java程序pid(pid為一個整數);
使用jstack pid >/usr/local/threaddump.txt (該命令將所有執行緒堆疊匯出到/usr/local/threaddump.txt檔案中)。
3、 分析/usr/local/threaddump.txt中的執行緒堆疊,找到非守護執行緒,jvm的GC執行緒不用看。
可以使用UltraEidt編輯器輔助查詢,搜尋“prio=”,列出所有的執行緒,可以很容易的看到daemon字樣的是守護執行緒,沒有daemon字樣的是非守護執行緒。
4、 本次跟蹤的threaddump.txt只找到一個非守護執行緒的堆疊,如下:
"pool-2-thread-1" prio=10 tid=0x00007f26244af000 nid=0xcb2 waiting on condition [0x00007f2616515000]
java.lang.Thread.State: TIMED_WAITING (parking)
at sun.misc.Unsafe.park(Native Method)
- parking to wait for <0x00000000c2aedf98> (a java.util.concurrent.locks.AbstractQueuedSynchronizer$ConditionObject)
at java.util.concurrent.locks.LockSupport.parkNanos(LockSupport.
at java.util.concurrent.locks.AbstractQueuedSynchronizer$ConditionObject.awaitNanos(AbstractQueuedSynchronizer.java:2025)
at java.util.concurrent.DelayQueue.take(DelayQueue.java:164)
at java.util.concurrent.ScheduledThreadPoolExecutor$DelayedWorkQueue.take(ScheduledThreadPoolExecutor.java:609)
at java.util.concurrent.ScheduledThreadPoolExecutor$DelayedWorkQueue.take(ScheduledThreadPoolExecutor.java:602)
at java.util.concurrent.ThreadPoolExecutor.getTask(ThreadPoolExecutor.java:947)
at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:907)
at java.lang.Thread.run(Thread.java:662)
5、 查詢與該執行緒堆疊有關業務程式碼,經查,對應的程式碼為:
//啟動就執行,之後每12小時呼叫一次(預設)
final int time = SystemInit.getSynLmpTime();
Executors.newScheduledThreadPool(1).scheduleAtFixedRate(new Runnable() {
@Override
public void run() {
executeSynBrandData();
executeSynCategoryData();
executeSynStoreData();
executeDeleteByBeforeDays(SystemInit.getDeleteBeforeDays());
}
}, 0, time, TimeUnit.HOURS);
修改方法:
外層程式碼要持有執行緒池的引用,以便shutdown時可以呼叫scheduledExecutorService.shutdown();進行關閉。
ScheduledExecutorService scheduledExecutorService = Executors.newScheduledThreadPool(1);
scheduledExecutorService.scheduleAtFixedRate(new Runnable() {
@Override
public void run() {