[英]Java - Thread stuck in “Park” status
我無法同時運行 100 多個線程。 當我進行線程轉儲時,我注意到其中許多都處於parked status
,即
停車等待 <0x00000000827e1760> (java.util.concurrent.locks.AbstractQueuedSynchronizer$ConditionObject)。
該程序在大約 25 個或更少線程的情況下運行良好。 有沒有辦法確定導致並發鎖的原因,和/或防止它? 這是使用 Executor 服務在 200 的固定池大小中運行的。
為缺少代碼道歉 - 它是專有的,有很多東西需要改變來混淆它。
您所指的類 (ConditionObject) 用於鎖定對象不被多個線程同時訪問。 Javadoc沒有描述您提到的線程狀態,但這是我的猜測:
您鎖定的對象被一個線程阻塞了很長時間,以至於其他線程開始堆積在鎖上。 一旦持有鎖的線程釋放它,下一個線程就會繼續獲取鎖。 在那個新線程完成他的工作之前,新線程會堆積在鎖后面。
如果我的猜測是正確的,那么可以:
在不知道您的問題域的情況下,我希望以上信息足以為您指明可能對您有所幫助的方向。
您是否在使用某種ThreadPoolExecutor,例如java.util.concurrent.Executors
類提供的那些? 也許您正面臨着任務被靜默未捕獲的異常完成的情況。 轉儲片段看起來像一個不活動的池線程,獲得不活動線程(應該是活動的)的一個原因是拋出異常但被默認線程池實現包圍。
LockSupport.park()
在線程池中,等待任務的線程被LockSupport.park();
鎖定LockSupport.park();
. 請參閱來自 openjdk 的java.util.concurrent.locks.AbstractQueuedSynchronizer
源代碼:
public final void await() throws InterruptedException {
// code omitted
while (!isOnSyncQueue(node)) {
LockSupport.park(this);
if ((interruptMode = checkInterruptWhileWaiting(node)) != 0)
break;
}
// code omitted
}
這意味着線程正在執行的任務已完成(是否突然),現在線程正在等待另一個任務執行(請參閱java.util.concurrent.ThreadPoolExecutor
openjdk source ):
private Runnable getTask() {
// ...
Runnable r = timed ?
workQueue.poll(keepAliveTime, TimeUnit.NANOSECONDS) :
workQueue.take(); <== the thread is blocked here
// ...
}
可以看到,線程在調用workQueue.take();
被鎖定了workQueue.take();
.
因此,很快,處於“停放狀態”的線程只是在前一個任務完成后等待新任務。
為什么我的任務不再運行?
完成任務的最合理原因是run()
的正常結束。 任務流結束,然后任務由各自的所有者線程釋放。 一旦線程釋放任務,只要有任務,它就准備好執行另一個任務。
檢查這種情況的一種直接方法是在run()
方法的末尾記錄一些內容:
class MyRunnable implements Runnable {
public void run() {
while(/*some condition*/) {
// do my things
}
log.info("My Runnable has finished for now!");
}
}
如果記錄一條消息還不夠,您可以調用另一個對象的方法。
木頭下的例外
另一個(最)可能的原因是任務執行期間拋出的未捕獲異常。 在線程池中,像這樣的未經檢查的異常將突然停止方法執行並(出人意料地)被吞入java.util.concurrent.FutureTask
對象中。 為了避免這樣的事情,我使用以下習語:
class MyRunnable implements Runnable {
public void run() {
while(/*some condition*/) {
try {
// do my things
} catch (Throwable throwable) {
handle(throwable);
}
}
log.info("My Runnable has finished for now!");
}
private void handle(Throwable throwable) {
// ...
}
}
或者根據我也使用的邏輯/性能要求:
public void run() {
try {
while(/*some condition*/) {
// do my things
}
} catch (Throwable throwable) {
handle(throwable);
}
System.out.println("My Runnable has finished for now!");
}
下面的代碼舉例說明了這里評論的問題:
package mypocs;
import java.util.concurrent.Executors;
import java.util.concurrent.ThreadPoolExecutor;
public class ExceptionSwallowingInThreadPoolsPoC {
public static void main(String[] args) {
ThreadPoolExecutor threadPoolExecutor = (ThreadPoolExecutor) Executors.newFixedThreadPool(10);
final Object LOCK = new Object();
threadPoolExecutor.submit(() -> {
while (true) {
synchronized (LOCK) {
System.out.println("Thread 'A' never ends");
}
Thread.sleep(1000L);
}
});
threadPoolExecutor.submit(() -> {
int lifespan = 3;
while (lifespan > 0) {
synchronized (LOCK) {
System.out.println("Thread 'B' is living for " + lifespan + " seconds");
}
lifespan--;
try {
Thread.sleep(1000L);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
System.out.println("Thread 'B' finished");
});
threadPoolExecutor.submit(() -> {
int lifespan = 3;
while (lifespan > 0) {
synchronized (LOCK) {
System.out.println("Thread 'C' is living for " + lifespan + " seconds");
}
lifespan--;
if (lifespan < 1) {
throw new RuntimeException("lifespan reached zero");
}
try {
Thread.sleep(1000L);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
System.out.println("Thread 'C' finished");
});
while (true) {
try {
Thread.sleep(1000L);
} catch (InterruptedException e) {
e.printStackTrace();
}
synchronized (LOCK) {
System.out.println("==== begin");
System.out.println("getActiveCount: " + threadPoolExecutor.getActiveCount());
System.out.println("getCompletedTaskCount: " + threadPoolExecutor.getCompletedTaskCount());
System.out.println("getPoolSize: " + threadPoolExecutor.getPoolSize());
System.out.println("==== end");
}
}
}
}
代碼應該輸出如下內容:
Thread 'A' never ends
Thread 'B' is living for 3 seconds
Thread 'C' is living for 3 seconds
Thread 'C' is living for 2 seconds
==== begin
getActiveCount: 3
getCompletedTaskCount: 0
getPoolSize: 3
==== end
Thread 'B' is living for 2 seconds
Thread 'A' never ends
==== begin
getActiveCount: 3
getCompletedTaskCount: 0
getPoolSize: 3
==== end
Thread 'C' is living for 1 seconds
Thread 'B' is living for 1 seconds
Thread 'A' never ends
Thread 'B' finished
==== begin
getActiveCount: 1
getCompletedTaskCount: 2
getPoolSize: 3
==== end
Thread 'A' never ends
Thread 'A' never ends
...
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.