gpt4 book ai didi

java - notify() 如何按顺序或随机唤醒线程

转载 作者:行者123 更新时间:2023-11-30 02:06:22 25 4
gpt4 key购买 nike

我知道notify会随机唤醒处于等待状态的线程。但是请看下面的代码

public class ThreadTest {
public static void main(String[] args) {
Object co = new Object();
System.out.println(co);

for (int i = 0; i < 1000; i++) {
MyThread t = new MyThread("Thread" + i, co);
t.start();
}

try {
TimeUnit.SECONDS.sleep(2);
System.out.println("-----Main Thread notify-----");

synchronized (co) {
co.notify();
}

TimeUnit.SECONDS.sleep(2);
System.out.println("Main Thread is end.");

} catch (InterruptedException e) {
e.printStackTrace();
}
}

static class MyThread extends Thread {
private String name;
private Object co;

public MyThread(String name, Object o) {
this.name = name;
this.co = o;
}

@Override
public void run() {
try {
synchronized (co) {
System.out.println(name + " is waiting.");
co.wait();
System.out.println(name + " has been notified.");
co.notify();
}
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}

}

但线程会按照线程调用 wait() 的顺序唤醒。意思是有人先调用wait(),它先被唤醒;有人第二次调用 wait(),第二次它就变弱了......

我认为这是我的代码错误导致的,但我不知道问题出在哪里。

为了方便展示,我将迭代次数从20次改为1000次,结果是一样的。

code.thread.ThreadTest
java.lang.Object@45ee12a7
Thread0 is waiting.
Thread1 is waiting.
Thread2 is waiting.
Thread3 is waiting.
Thread4 is waiting.
Thread5 is waiting.
Thread6 is waiting.
Thread7 is waiting.
Thread9 is waiting.
Thread10 is waiting.
Thread11 is waiting.
Thread8 is waiting.
Thread12 is waiting.
Thread13 is waiting.
Thread14 is waiting.
Thread15 is waiting.
Thread16 is waiting.
Thread17 is waiting.
Thread18 is waiting.
Thread19 is waiting.
-----Main Thread notify-----
Thread0 has been notified.
Thread1 has been notified.
Thread2 has been notified.
Thread3 has been notified.
Thread4 has been notified.
Thread5 has been notified.
Thread6 has been notified.
Thread7 has been notified.
Thread9 has been notified.
Thread10 has been notified.
Thread11 has been notified.
Thread8 has been notified.
Thread12 has been notified.
Thread13 has been notified.
Thread14 has been notified.
Thread15 has been notified.
Thread16 has been notified.
Thread17 has been notified.
Thread18 has been notified.
Thread19 has been notified.
Main Thread is end.

Process finished with exit code 0

最佳答案

The specification of notify()说:

If any threads are waiting on this object, one of them is chosen to be awakened. The choice is arbitrary and occurs at the discretion of the implementation.

这意味着您不能期望任何特定的顺序,而实现可以使用它想要的任何特定顺序,包括线程调用 wait 的顺序。

没有理由说实现应该实现混洗。那样只会浪费资源。给予实现自由的原因是允许它们在合适的时候使用更高效的算法,而不必维护顺序。

因此,由于存储结构不同,不同的实现可能会以相反的顺序唤醒它们。如果实现切换到高于阈值的不同存储结构,它也可能会随着一定数量的排队线程而改变。

除此之外,你的测试代码很特别。您的主线程在调用 notify() 之前会等待很长时间,因此很可能所有线程都已进入等待状态并存储在 JVM 使用的任何数据结构中。然后,一次只有一个待处理的 notify(),因为您让已唤醒的线程执行下一个 notify()。如果允许操作重叠,图片可能会发生巨大变化。

那么,底层数据结构可能不是纯粹的 FIFO。此外,如果有待处理的 notify(),实现允许调用 wait() 的线程立即继续,而不考虑等待队列,绕过所有的实现,这是很常见的。已经将线程排入队列,因为这样效率更高。

另一点是,如果有多个待处理的notify(),则已被唤醒的线程必须竞争重新获取对象监视器。这取决于操作系统的调度程序和实际的系统负载,哪个线程会在这里成功,因此即使线程按照排队的顺序被唤醒,由于 JVM 无法控制的细节,线程也可能会在这个地方重载。

此外,不要忘记该规范允许虚假唤醒。因此,无法单独唤醒单个线程的 JVM 可以通过单个 notify() 调用来唤醒多个线程,而不会违反规范。

关于java - notify() 如何按顺序或随机唤醒线程,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/51231103/

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