gpt4 book ai didi

Java - 线程陷入 "Park"状态

转载 作者:行者123 更新时间:2023-12-01 19:59:01 35 4
gpt4 key购买 nike

我无法同时运行超过 100 个线程。当我进行线程转储时,我注意到其中许多线程处于停放状态,即

parking to wait for <0x00000000827e1760> (java.util.concurrent.locks.AbstractQueuedSynchronizer$ConditionObject).

程序在大约 25 个或更少的线程下运行良好。有没有办法确定导致并发锁的原因,和/或防止它?这是使用 Executor 服务在大小为 200 的固定池中运行的。

对缺少代码表示歉意 - 它是专有的,需要进行很多更改来混淆它。

最佳答案

您是否使用某种 ThreadPoolExecutor比如java.util.concurrent.Executors提供的类(class)?也许您正面临着任务通过未捕获的静默异常来完成的情况。转储片段看起来像一个不活动的池线程,而获得不活动线程(应该是 Activity 的)的原因之一是抛出异常,但被默认线程池实现包围。

LockSupport.park()

在线程池中,等待任务的线程被LockSupport.park();锁定。 。请参阅java.util.concurrent.locks.AbstractQueuedSynchronizer source from openjdk :

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(); 中被锁定。 。

因此,很快,处于“停放状态”的线程只是在先前的任务完成后等待新的任务。

为什么我的任务不再运行?

完成任务的最合理原因是 run() 的正常结束。 。任务流完成,然后任务由各自的所有者线程释放。一旦线程释放了任务,只要有任务,它就可以执行另一个任务。

检查这种情况的一种直接方法是在 run() 的末尾记录一些内容。方法:

class MyRunnable implements Runnable {

public void run() {
while(/*some condition*/) {
// do my things
}
log.info("My Runnable has finished for now!");
}
}

如果记录消息还不够,您可以调用另一个对象的方法。

木头下的异常(exception)

另一个(最)可能的原因是任务执行期间抛出未捕获的异常。在线程池中,像这样的未经检查的异常将突然停止方法执行并(令人惊讶地)被吞入 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
...

关于Java - 线程陷入 "Park"状态,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/48613567/

35 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com