提问人:Mr.Chen 提问时间:3/1/2023 更新时间:4/28/2023 访问量:71
当我用 jdk1.8 运行以下代码时没有问题,但是当我用 jdk11 运行它时它会阻塞
There is no problem when I run the following code with jdk1.8, but it will block when I run it with jdk11
问:
public class Test {
public static int num = 0;
public static void main(String[] args) {
new Thread(Test::printer, "t0").start();
new Thread(Test::printer, "t1").start();
new Thread(Test::printer, "t2").start();
}
public static void printer() {
synchronized (Test.class) {
while (num < 100) {
if (Thread.currentThread().getName().contains(String.valueOf(num % 3))) {
System.out.println(Thread.currentThread().getName() + ": " + num++);
}
Test.class.notifyAll();
try {
Test.class.wait();
} catch (InterruptedException e) {
throw new RuntimeException(e);
}
}
Test.class.notifyAll();
}
}
}
当我用 jdk1.8.It 可以输出 0 到 99 运行以下代码时没有问题,但是当我使用 jdk11 运行代码时,它会在 2 或 3 停止,我用来检查线程状态,结果如下:jstack
"Monitor Ctrl-Break" #21 daemon prio=5 os_prio=0 cpu=15.63ms elapsed=10.26s tid=0x000001ccc56cf800 nid=0x5424 runnable [0x000000a410efe000]
java.lang.Thread.State: RUNNABLE
at java.net.SocketInputStream.socketRead0([email protected]/Native Method)
at java.net.SocketInputStream.socketRead([email protected]/SocketInputStream.java:115)
at java.net.SocketInputStream.read([email protected]/SocketInputStream.java:168)
at java.net.SocketInputStream.read([email protected]/SocketInputStream.java:140)
at sun.nio.cs.StreamDecoder.readBytes([email protected]/StreamDecoder.java:284)
at sun.nio.cs.StreamDecoder.implRead([email protected]/StreamDecoder.java:326)
at sun.nio.cs.StreamDecoder.read([email protected]/StreamDecoder.java:178)
- locked <0x00000007181038c8> (a java.io.InputStreamReader)
at java.io.InputStreamReader.read([email protected]/InputStreamReader.java:181)
at java.io.BufferedReader.fill([email protected]/BufferedReader.java:161)
at java.io.BufferedReader.readLine([email protected]/BufferedReader.java:326)
- locked <0x00000007181038c8> (a java.io.InputStreamReader)
at java.io.BufferedReader.readLine([email protected]/BufferedReader.java:392)
at com.intellij.rt.execution.application.AppMainV2$1.run(AppMainV2.java:56)
"t0" #22 prio=5 os_prio=0 cpu=0.00ms elapsed=10.25s tid=0x000001ccc56d0000 nid=0x6560 in Object.wait() [0x000000a4110fe000]
java.lang.Thread.State: BLOCKED (on object monitor)
at java.lang.Object.wait([email protected]/Native Method)
- waiting on <0x0000000718113e10> (a java.lang.Class for com.chen.Test)
at java.lang.Object.wait([email protected]/Object.java:328)
at com.chen.Test.printer(Test.java:21)
- waiting to re-lock in wait() <0x0000000718113e10> (a java.lang.Class for com.chen.Test)
at com.chen.Test$$Lambda$14/0x0000000800066840.run(Unknown Source)
at java.lang.Thread.run([email protected]/Thread.java:834)
"t1" #23 prio=5 os_prio=0 cpu=3718.75ms elapsed=10.25s tid=0x000001ccc56d1000 nid=0x7b8 in Object.wait() [0x000000a4111ff000]
java.lang.Thread.State: BLOCKED (on object monitor)
at java.lang.Object.wait([email protected]/Native Method)
- waiting on <no object reference available>
at java.lang.Object.wait([email protected]/Object.java:328)
at com.chen.Test.printer(Test.java:21)
- waiting to re-lock in wait() <0x0000000718113e10> (a java.lang.Class for com.chen.Test)
at com.chen.Test$$Lambda$15/0x0000000800066c40.run(Unknown Source)
at java.lang.Thread.run([email protected]/Thread.java:834)
"t2" #24 prio=5 os_prio=0 cpu=4140.63ms elapsed=10.25s tid=0x000001ccc56d2000 nid=0x6620 in Object.wait() [0x000000a4112ff000]
java.lang.Thread.State: WAITING (on object monitor)
at java.lang.Object.wait([email protected]/Native Method)
- waiting on <no object reference available>
at java.lang.Object.wait([email protected]/Object.java:328)
at com.chen.Test.printer(Test.java:21)
- waiting to re-lock in wait() <0x0000000718113e10> (a java.lang.Class for com.chen.Test)
at com.chen.Test$$Lambda$16/0x0000000800066040.run(Unknown Source)
at java.lang.Thread.run([email protected]/Thread.java:834)
t0 和 t1 都被阻止了,但是它们都没有得到 cpu,那么谁能告诉我为什么我得到了这个结果?
答:
-2赞
NickH
3/1/2023
#1
当我从 java 8 更新到 11 时。我不得不添加额外的依赖项并从 pom 中排除一些现有的依赖项。Java 11 有许多 jar 在 java 8 中没有。希望这对:)有所帮助
评论
0赞
steffen
3/7/2023
#2
代码功能摘要
您创建 3 个线程并让它们并行运行。在循环中,如果当前线程负责这样做,则它会递增一个数字 ()。仍然在循环中,您让 JVM 选择其他线程之一以继续,同时将当前线程置于等待状态。static printer()
synchronized
%3
会发生什么
notifyAll():
有关线程可以成为监视器所有者的方式的说明,请参阅 notify 方法。
notify():
如果有任何线程在此对象上等待,则选择其中一个线程进行唤醒。选择是任意的,由实施自行决定。
发生的情况是,监视器采集仅在 3 个线程中的 2 个线程之间切换,而恰好负责递增当前值的第三个线程不会脱颖而出。
哦,您需要创建变量以确保所有线程都读取最新的更新值。我认为这可能已经是观察到的行为的正当理由。volatile
评论