最大的不同是在等待時 wait 會釋放鎖,而 sleep 一直持有鎖。Wait 通常被用於線
程間交互,sleep 通常被用於暫停執行。
直接了解的深入一點吧:
在 Java 中線程的狀態一共被分成 6 種:
初始態:NEW
創建一個 Thread 對象,但還未調用 start()啟動線程時,線程處於初始態。
運行態:RUNNABLE
在 Java 中,運行態包括就緒態 和 運行態。
就緒態 該狀態下的線程已經獲得執行所需的所有資源,只要 CPU 分配執行權就
能運行。所有就緒態的線程存放在就緒隊列中。
運行態 獲得 CPU 執行權,正在執行的線程。由於一個 CPU 同一時刻只能執行一
條線程,因此每個 CPU 每個時刻只有一條運行態的線程。
阻塞態
當一條正在執行的線程請求某一資源失敗時,就會進入阻塞態。而在 Java 中,阻
塞態專指請求鎖失敗時進入的狀態。由一個阻塞隊列存放所有阻塞態的線程。處
於阻塞態的線程會不斷請求資源,一旦請求成功,就會進入就緒隊列,等待執行。
PS:鎖、IO、Socket 等都資源。
等待態
當前線程中調用 wait、join、park 函數時,當前線程就會進入等待態。也有一個
等待隊列存放所有等待態的線程。線程處於等待態表示它需要等待其他線程的指
示才能繼續運行。進入等待態的線程會釋放 CPU 執行權,並釋放資源(如:鎖)
超時等待態
當運行中的線程調用 sleep(time)、wait、join、parkNanos、parkUntil 時,就
會進入該狀態;它和等待態一樣,並不是因為請求不到資源,而是主動進入,並
且進入后需要其他線程喚醒;進入該狀態后釋放 CPU 執行權 和 占有的資源。與
等待態的區別:到了超時時間后自動進入阻塞隊列,開始競爭鎖。
終止態
線程執行結束后的狀態。
注意:
wait()方法會釋放 CPU 執行權 和 占有的鎖。
sleep(long)方法僅釋放 CPU 使用權,鎖仍然占用;線程被放入超時等待隊列,與
yield 相比,它會使線程較長時間得不到運行。
yield()方法僅釋放 CPU 執行權,鎖仍然占用,線程會被放入就緒隊列,會在短時
間內再次執行。
wait 和 notify 必須配套使用,即必須使用同一把鎖調用;
wait 和 notify 必須放在一個同步塊中調用 wait 和 notify 的對象必須是他們所處
同步塊的鎖對象。