gpt4 book ai didi

如果线程结束,Java Thread.join() 方法将卡住

转载 作者:行者123 更新时间:2023-11-30 04:11:42 46 4
gpt4 key购买 nike

我有这样的代码:

public void testThreads() throws Exception {
MyThreadManager mgr = createAndStartMyManager();
Thread t1 = createMyThread(mgr, 1);
Thread t2 = createMyThread(mgr, 2);

t1.start();
t2.start();

//do some checks

t1.join();
t2.join();
}

MyThreadManager 使用线程进行操作,并且可能随时中断其中的任何线程。因为这是测试用例的一部分,并且我需要调试正在运行的线程,所以我添加了 joins 来让测试等待完成调试(测试完成时 JUnit 会断开调试器连接)。

问题是,在某些情况下连接会挂起 - jstack 输出如下:

    at java.lang.Object.wait(Native Method)
- waiting on <0xeec68eb0> (a java.lang.Thread)
at java.lang.Thread.join(Thread.java:1143)
- locked <0xeec68eb0> (a java.lang.Thread)
at java.lang.Thread.join(Thread.java:1196)
at MyClass.testThreads(MyClass.java:100)

根据join JDK(我使用1.6.0_07)实现,线程似乎在调用isAlivewait之间完成(标记为在源代码中):

public final synchronized void join(long millis)
throws InterruptedException {
long base = System.currentTimeMillis();
long now = 0;

if (millis < 0) {
throw new IllegalArgumentException("timeout value is negative");
}

if (millis == 0) {
while (isAlive()) {
// -----> here ???? <------
wait(0);
}
} else {
while (isAlive()) {
long delay = millis - now;
if (delay <= 0) {
break;
}
wait(delay);
now = System.currentTimeMillis() - base;
}
}
}

我对 ThreadPoolExecutor 和 FutureTask 进行了相同的尝试,但行为是相同的(它挂起)。

所以我的问题是,如果我的竞争条件属实,以及如何在没有任何挂起的情况下清楚地加入线程......

谢谢

最佳答案

So my question is, if I am true with the race condition and also how to clearly join threads without any hanging ...

不,该方法中没有竞争。由于该方法是同步,竞争条件已解决。如果这是一个竞争条件,那么大量 Java 线程可能在此之前就已经失败了。我怀疑您加入的线程仍在运行。这不可能吗?

The problem is, that in some cases the join hangs - jstack output is like this:

此堆栈输出显示它在 join() 中阻塞。正如 @Holger 提到的,你能看到 t1 或 t2 堆栈也在那里吗?为线程命名可能很有用,以便您可以在堆栈跟踪输出中更轻松地看到它们:

Thread t1 = createMyThread(mgr, 1, "t1"); // name passed to thread constructor
Thread t2 = createMyThread(mgr, 2, "t2"); // name passed to thread constructor

MyThreadManager operates with threads and may interrupt

你在调用thread.interrupt()吗?如果是这样,这不会导致线程停止,除非您正在测试线程中断位和/或正确处理 InterruptedException

while (!Thread.currentThread().isInterrupted()) {

如果第 3 方库在捕获 InterruptedException 时未重新启用中断位,您还需要进行处理。正确的模式是执行以下操作:

try {
...
} catch (InterruptedException ie) {
// re-enable interrupt bit since catching InterruptedException clears it
Thread.currentThread().interrupt();
// handle the interrupt by maybe quitting the thread
return;
}

I tried the same with ThreadPoolExecutor and FutureTask, but the behavior was the same (it is hanging).

使用 TPE,您需要确保执行器在所有作业提交给它之后关闭。然而,这将导致您的应用程序挂起,并且不会显示与 join() 中阻塞相同的行为。

关于如果线程结束,Java Thread.join() 方法将卡住,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/19455159/

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