Java中notify是順序喚醒還是隨機喚醒的
前言:
做 Java 開發(fā)的小伙伴,對 wait 方法和 notify 方法應(yīng)該都比較熟悉,這兩個方法在線程通訊中使用的頻率非常高,但對于 notify 方法的喚醒順序,有很多小伙伴的理解都是錯誤的,有很多人會認為 notify 是隨機喚醒的,但它真的是隨機喚醒的嗎?
帶著這個疑問,我們嘗試休眠 100 個線程,再喚醒 100 個線程,并把線程休眠和喚醒的順序保持到兩個集合中,最后再打印一下這兩個集合,看一下它們的執(zhí)行順序,如果它們的順序是一致的,那說明 notify 是順序喚醒的,否則則是隨機喚醒的,
notify 測試代碼如下:
import java.util.ArrayList;
import java.util.List;
public class NotifyExample {
// 保存休眠線程的順序
private static List<String> waitList = new ArrayList<>();
// 保存喚醒線程的順序
private static List<String> notifyList = new ArrayList<>();
public static void main(String[] args) throws InterruptedException {
final Object lock = new Object();
// 休眠 100 個線程
for (int i = 0; i < 100; i++) {
String threadName = Integer.toString(i); // 定義線程名
new Thread(() -> {
// 獲取當(dāng)前執(zhí)行線程的線程名
String currThreadName = Thread.currentThread().getName();
synchronized (lock) {
waitList.add(currThreadName); // 存入等待 list
try {
lock.wait(); // 休眠線程
} catch (InterruptedException e) {
e.printStackTrace();
}
notifyList.add(currThreadName); // 存儲喚醒 list
}
}, threadName).start();
}
Thread.sleep(1000);
// 喚醒 100 個線程
for (int i = 0; i < 100; i++) {
synchronized (lock) {
lock.notify(); // 喚醒線程
}
}
// 打印 2 個線程列表
System.out.println("等待線程順序:" + waitList);
System.out.println("喚醒線程順序:" + waitList);
}
}以上程序的執(zhí)行結(jié)果如下圖所示:

從上述打印的結(jié)果我們可以看出,使用 notify 并不是隨機喚醒的,而是順序喚醒的,雖然以上代碼能證明這個結(jié)論,但為了更清楚的解釋這個問題,我們查看了 notify 的實現(xiàn)源碼,
它的源碼內(nèi)容如下:

簡單翻譯一下上面的重點內(nèi)容,notify 選擇喚醒的線程是任意的,但具體的實現(xiàn)還要依賴于 JVM。也就是說 notify 的喚醒規(guī)則,最終取決于 JVM 廠商,不同的廠商的實現(xiàn)可能是不同的,比如阿里的 JVM 和 Oracle 的 JVM,關(guān)于 notify 的喚醒規(guī)則可能是不一樣的。
那作為一個普通的程序員我們要研究的就是官方的 JVM 也就是 HotSpot 虛擬機,它的 notify 實現(xiàn)源碼在 ObjectMonitor.cpp 中,
具體源碼如下:

DequeueWaiter 方法實現(xiàn)的源碼如下:

從上述源碼可以看出,在進行喚醒時,每次會從 _WaitSet 等待集合中獲取第一個元素進行出隊操作,這也說明了 notify 是順序喚醒的。
總結(jié):
notify 喚醒線程的規(guī)則是隨機喚醒還是順序喚醒取決于 JVM 的具體實現(xiàn),作為主流的 HotSpot 虛擬機中的 notify 的喚醒規(guī)則是順序的,也就是 notify 會按照線程的休眠順序,依次喚醒線程。
到此這篇關(guān)于Java中notify是順序喚醒還是隨機喚醒的的文章就介紹到這了,更多相關(guān)Java notify喚醒規(guī)則內(nèi)容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
相關(guān)文章
Mybatis?Mapper中多參數(shù)方法不使用@param注解報錯的解決
這篇文章主要介紹了Mybatis?Mapper中多參數(shù)方法不使用@param注解報錯的解決方案,具有很好的參考價值,希望對大家有所幫助。如有錯誤或未考慮完全的地方,望不吝賜教。2022-01-01
Spring Boot3.x自動配置不生效的排查與解決方法(IDEA 文件夾命名導(dǎo)致的問題)
在SpringBoot多模塊項目中,自動配置類未生效的問題通常源于文件路徑錯誤,通過檢查和修正AutoConfiguration.imports文件的實際路徑,可以解決自動配置不生效的問題,感興趣的朋友跟隨小編一起看看吧2024-11-11
java解析xml的4種方式的優(yōu)缺點對比及實現(xiàn)詳解
這篇文章主要介紹了java解析xml的4種方式的優(yōu)缺點對比及實現(xiàn)詳解,文中通過示例代碼介紹的非常詳細,對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價值,需要的朋友可以參考下2019-07-07

