下面的代码用jdk1.8运行没问题,用jdk11运行会阻塞

问题描述 投票:0回答:2
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运行下面的代码没有问题。它可以输出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,所以谁能告诉我为什么我得到这个结果?

java synchronized notify
2个回答
0
投票

总结你的代码做什么

你创建了 3 个线程并让它们并行运行

static printer()
。在
synchronized
循环中,如果当前线程负责这样做,则当前线程会递增一个数字 (
%3
)。仍在循环内,让 JVM 选择其他线程之一继续,同时将当前线程置于等待状态。

会发生什么

notifyAll():

有关线程可以成为监视器所有者的方式的描述,请参阅通知方法。

通知():

如果有任何线程正在等待这个对象,则选择其中一个被唤醒。选择是任意的,由实现自行决定。

发生的情况是监视器获取仅在 3 个线程中的 2 个之间切换,而恰好负责递增当前值的第三个线程没有出现。

哦,您需要使变量

volatile
以确保所有线程读取最新更新的值。我认为这可能已经是观察到的行为的正当理由。


-2
投票

当我从 Java 8 更新到 11 时。我不得不添加额外的依赖项并从 pom.xml 中排除一些现有的依赖项。 Java 11 有很多 java 8 中没有的 jar。希望这有帮助:)

© www.soinside.com 2019 - 2024. All rights reserved.