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'被稱爲 - 但是你的日誌記錄*還*無可爭議地表明它被稱爲同一個實例嗎? –