tomcat:等待条件线程
tomcat: Waiting on condition thread
我正在调查 tomcat 关闭进程的奇怪问题:在运行 shutdown.sh 之后 java 进程仍然出现(我使用 ps -ef|grep tomcat
检查它)
情况有点复杂,因为我对服务器的访问非常有限(例如没有调试)
我使用远程 jConsole
和热点功能进行了线程转储(通过使用 kill -3 <PID>
)和堆转储。
在查看线程转储后,我发现了这个:
"pool-2-thread-1" #74 prio=5 os_prio=0 tid=0x00007f3354359800 nid=0x7b46 waiting on condition [0x00007f333e55d000]
java.lang.Thread.State: WAITING (parking)
at sun.misc.Unsafe.park(Native Method)
- parking to wait for <0x00000000c378d330> (a java.util.concurrent.locks.AbstractQueuedSynchronizer$ConditionObject)
at java.util.concurrent.locks.LockSupport.park(LockSupport.java:175)
at java.util.concurrent.locks.AbstractQueuedSynchronizer$ConditionObject.await(AbstractQueuedSynchronizer.java:2039)
at java.util.concurrent.ScheduledThreadPoolExecutor$DelayedWorkQueue.take(ScheduledThreadPoolExecutor.java:1081)
at java.util.concurrent.ScheduledThreadPoolExecutor$DelayedWorkQueue.take(ScheduledThreadPoolExecutor.java:809)
at java.util.concurrent.ThreadPoolExecutor.getTask(ThreadPoolExecutor.java:1067)
at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1127)
at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:617)
at java.lang.Thread.run(Thread.java:748)
所以,我对这个问题的理解是:有一个资源(数据库连接或其他东西)在CachedThreadpool中使用,这个资源现在被锁定了,
并防止线程 pool-2-thread-1
停止。假设这个线程不是守护进程——JVM 不能优雅地停止。
有没有办法找出哪个资源被锁定,从哪里锁定以及如何避免?另一个问题是——如何防止这种情况发生?
另一个是:地址 0x00007f333e55d000 是做什么用的?
谢谢!
挣扎了一阵才发现,冻结的线程总是同名的pool-2-thread-1
。我 grep 项目的所有源以查找任何启动任何计划线程池的地方:Executors#newScheduledThreadPool
。经过大量时间后,我记录了所有这些地方,线程池中的线程名称。
再重启一次服务器,就搞定了!
我找到了一个线程池,它只用一个线程启动并使用了以下代码:
private void shutdownThreadpool(int tries) {
try {
boolean terminated;
LOGGER.debug("Trying to shutdown thread pool in {} tries", tries);
pool.shutdown();
do {
terminated = pool.awaitTermination(WAIT_ON_SHUTDOWN,TimeUnit.MILLISECONDS);
if (--tries == 0
&& !terminated) {
LOGGER.debug("After 10 attempts couldn't shutdown thread pool, force shutdown");
pool.shutdownNow();
terminated = pool.awaitTermination(WAIT_ON_SHUTDOWN, TimeUnit.MILLISECONDS);
if (!terminated) {
LOGGER.debug("Cannot stop thread pool even with force");
LOGGER.trace("Some of the workers doesn't react to Interruption event properly");
terminated = true;
}
} else {
LOGGER.info("After {} attempts doesn't stop", tries);
}
} while (!terminated);
LOGGER.debug("Successfully stop thread pool");
} catch (final InterruptedException ie) {
LOGGER.warn("Thread pool shutdown interrupted");
}
}
之后问题就解决了。
我正在调查 tomcat 关闭进程的奇怪问题:在运行 shutdown.sh 之后 java 进程仍然出现(我使用 ps -ef|grep tomcat
检查它)
情况有点复杂,因为我对服务器的访问非常有限(例如没有调试)
我使用远程 jConsole
和热点功能进行了线程转储(通过使用 kill -3 <PID>
)和堆转储。
在查看线程转储后,我发现了这个:
"pool-2-thread-1" #74 prio=5 os_prio=0 tid=0x00007f3354359800 nid=0x7b46 waiting on condition [0x00007f333e55d000]
java.lang.Thread.State: WAITING (parking)
at sun.misc.Unsafe.park(Native Method)
- parking to wait for <0x00000000c378d330> (a java.util.concurrent.locks.AbstractQueuedSynchronizer$ConditionObject)
at java.util.concurrent.locks.LockSupport.park(LockSupport.java:175)
at java.util.concurrent.locks.AbstractQueuedSynchronizer$ConditionObject.await(AbstractQueuedSynchronizer.java:2039)
at java.util.concurrent.ScheduledThreadPoolExecutor$DelayedWorkQueue.take(ScheduledThreadPoolExecutor.java:1081)
at java.util.concurrent.ScheduledThreadPoolExecutor$DelayedWorkQueue.take(ScheduledThreadPoolExecutor.java:809)
at java.util.concurrent.ThreadPoolExecutor.getTask(ThreadPoolExecutor.java:1067)
at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1127)
at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:617)
at java.lang.Thread.run(Thread.java:748)
所以,我对这个问题的理解是:有一个资源(数据库连接或其他东西)在CachedThreadpool中使用,这个资源现在被锁定了,
并防止线程 pool-2-thread-1
停止。假设这个线程不是守护进程——JVM 不能优雅地停止。
有没有办法找出哪个资源被锁定,从哪里锁定以及如何避免?另一个问题是——如何防止这种情况发生? 另一个是:地址 0x00007f333e55d000 是做什么用的?
谢谢!
挣扎了一阵才发现,冻结的线程总是同名的pool-2-thread-1
。我 grep 项目的所有源以查找任何启动任何计划线程池的地方:Executors#newScheduledThreadPool
。经过大量时间后,我记录了所有这些地方,线程池中的线程名称。
再重启一次服务器,就搞定了!
我找到了一个线程池,它只用一个线程启动并使用了以下代码:
private void shutdownThreadpool(int tries) {
try {
boolean terminated;
LOGGER.debug("Trying to shutdown thread pool in {} tries", tries);
pool.shutdown();
do {
terminated = pool.awaitTermination(WAIT_ON_SHUTDOWN,TimeUnit.MILLISECONDS);
if (--tries == 0
&& !terminated) {
LOGGER.debug("After 10 attempts couldn't shutdown thread pool, force shutdown");
pool.shutdownNow();
terminated = pool.awaitTermination(WAIT_ON_SHUTDOWN, TimeUnit.MILLISECONDS);
if (!terminated) {
LOGGER.debug("Cannot stop thread pool even with force");
LOGGER.trace("Some of the workers doesn't react to Interruption event properly");
terminated = true;
}
} else {
LOGGER.info("After {} attempts doesn't stop", tries);
}
} while (!terminated);
LOGGER.debug("Successfully stop thread pool");
} catch (final InterruptedException ie) {
LOGGER.warn("Thread pool shutdown interrupted");
}
}
之后问题就解决了。