2
在分析所述生产环境中的一个的日志,我看到一个线程在“等待”状态上的CountDownLatch等待()线程阻塞CountDownLatch等待()时计数为0
...sun.misc.Unsafe.park(Native Method)
...java.util.concurrent.locks.LockSupport.park(Unknown Source)
...java.util.concurrent.locks.AbstractQueuedSynchronizer.parkAndCheckInterrupt(Unknown Source)
...java.util.concurrent.locks.AbstractQueuedSynchronizer.doAcquireSharedInterruptibly(Unknown Source)
...java.util.concurrent.locks.AbstractQueuedSynchronizer.acquireSharedInterruptibly(Unknown Source)
...java.util.concurrent.CountDownLatch.await(Unknown Source)
闩锁是初始化为1,另一个线程在锁存器的同一个实例上调用了countDown()方法,但主线程仍然锁定在锁存器上。这导致jvm被无限期地挂起。
即使锁存计数达到零也会被阻塞听起来不合理,我正在寻找进一步解决此问题的建议。
任何想法?
注 - 使用的JVM版本如下
Java版本 “1.5.0_15” 的Java(TM)2运行环境,标准版(建立1.5.0_15-B04) 的HotSpot的Java(TM)客户端VM(建立1.5.0_15-B04,混合模式,共享)
更新 - 下面是我说的线程的代码段中
private class MyRunnable implements Runnable, Thread.UncaughtExceptionHandler {
private AtomicBoolean shouldStop = new AtomicBoolean(false);
private CountDownLatch stopLatch = new CountDownLatch(1);
private Thread currentThread;
public void run() {
Thread.currentThread().setName("My Thread");
Thread.currentThread().setUncaughtExceptionHandler(this);
currentThread = Thread.currentThread();
if (currentThread.isInterrupted()) {
logger.debug("The pool thread had its interrupted stattus set. Clearing...");
Thread.interrupted();
logger.debug("The pool thread had its interrupted stattus set. Clearing...DONE");
}
try {
doBusinessLogic(shouldStop);
} catch (Exception e) {
logger.error("An exception was encountered in the thread", e);
} finally {
if (currentThread.isInterrupted()) {
logger.debug("Clearing interupted status for the thread and returning to pool...");
Thread.interrupted();
}
stopLatch.countDown();
logger.debug("Stopped task after counting down on the latch");
}
}
public void stopThread() {
shouldStop.set(true);
logger.debug("Stop flag was set to true.. waiting for thread method to return...");
try {
stopLatch.await();
logger.debug("Stop flag was set to true... task has finished. Returning.");
} catch (InterruptedException e) {
logger.error("Interrupted while awaiting thread stop event...", e);
}
}
public void uncaughtException(Thread t, Throwable e) {
logger.error("An uncaught exception occurred in the task thread ", e);
}
private void doBusinessLogic(AtomicBoolean shouldStop) {
long sleepPeriod = 11;
while (!shouldStop.get()) {
try {
Thread.sleep(sleepPeriod);
} catch (InterruptedException e) {
logger.debug("Thread was interrupted.Clearing interrupted status and proceeding", e);
if (Thread.currentThread().isInterrupted())
Thread.interrupted();
}
if (shouldStop.get()) {
logger.debug("Stop flag was set. Returning.");
return;
}
try {
logger.debug("Performing business logic...");
//.....
logger.debug("Performing business logic...DONE");
} catch (Throwable e) {
logger.error("An exception occurred", e);
}
if (shouldStop.get()) {
logger.debug("Stop flag was set. Returning.");
return;
}
}
}
}
这是我在看日志
DEBUG [main Thread] - Stop flag was set to true.. waiting for thread method to return...
DEBUG [My Thread] - Stop flag was set. Returning.
DEBUG [My Thread] - Stopped task after counting down on the latch
记录器语句后latch.await()是从来没有打印,并且线程转储也表示主线程被阻塞上的闩锁。
你*说*在同一个实例上调用了'countDown()',但我更倾向于认为代码和诊断中存在一个错误,而不是JRE库中的错误。你能制作一个简短但完整的程序来证明这个问题吗? –
如果我可以证明它,我可能已经知道可能已知的根本原因:)。我说countDown()被调用的原因是因为记录器语句表明它。在调用countDown()之后添加了日志语句,这些日志语句在日志中显示。虽然线程转储表明主线程仍然等待锁存计数为零。 –
我敢说'countDown'被称为 - 但是你的日志记录*还*无可争议地表明它被称为同一个实例吗? –