1. 程式人生 > >Java執行緒阻塞方法sleep()和wait()精煉詳解

Java執行緒阻塞方法sleep()和wait()精煉詳解

一、前期基礎知識儲備

sleep()和wait()方法都是Java中造成執行緒阻塞的方法。感興趣的讀者可以參見筆者之前的文章《Java中什麼方法導致執行緒阻塞》,裡面詳細講述了為什麼Java要造成執行緒阻塞和Java中造成執行緒阻塞的幾種方法。

執行緒的生命週期

這是筆者在谷歌圖片中找到的一張簡單描述執行緒生命週期的圖片,可以看到,一個執行緒正常的生命週期中會經歷“建立”“就緒”“執行”“阻塞”“執行”“死亡”等幾個生命週期,其中“阻塞”是我們開發者非常需要關注的,因為通過Java提供的阻塞方法,可以做到資源和執行緒最合理的調配,而其中sleep()和wait()方法就是Java中實現執行緒阻塞的關鍵性方法。

(2)sleep()和wait()方法的阻塞執行緒的場景

我們這裡,來看第二張圖片,這張圖片就比較詳細的向我們展現了一個執行緒的完整生命週期中發生的各種“事件”和呼叫的各種方法。我們來總結一下sleep()和wait()方法的阻塞場景。

sleep()實現執行緒阻塞的方法,我們稱之為“執行緒睡眠”,方式是超時等待,怎麼理解?就是sleep()通過傳入“睡眠時間”作為方法的引數,時間一到就從“睡眠”中“醒來”;

wait()方法實現執行緒阻塞的方法,我們稱之為“執行緒等待”,方式有兩種:

1)和sleep()方法一樣,通過傳入“睡眠時間”作為引數,時間到了就“醒了”;

2)不傳入時間,進行一次“無限期的等待”,只用通過notify()方法來“喚醒”。

二、sleep()和wait()的區別

通過上面兩幅圖的展示和筆者的相關描述,相信讀者你已經有幾分清楚了,sleep()和wait()方法的區別之一,就是實現執行緒阻塞的方式不一樣。

那麼sleep()和wait()二者還有一個很大的區別就是,二者“是否釋放同步鎖”不一樣。我們都知道,多執行緒開發中,為了實現不同執行緒間的同步會採用同步鎖的方式——synchronized即線上程使用一個資源時為其加鎖,這樣其他的執行緒便不能訪問那個資源了,直到解鎖後才可以訪問。感興趣的讀者可以參考筆者之前文章《利用synchronized實現執行緒同步》裡面詳細介紹了多執行緒開發中利用synchronized實現執行緒同步的方式。

而使用sleep()和wait()兩種方法對於“CPU執行權”和“同步鎖”的方式不同:

sleep()釋放CPU執行權,但不釋放同步鎖

wait()釋放CPU執行權,也釋放同步鎖,使得其他執行緒可以使用同步控制塊或者方法

以上,就是sleep()和wait()方法的兩個關鍵性區別

總結:綜上我們利用下表展示sleep()和wait()的所有區別:

ps:謝謝博友的更正。這裡進行改正: wait()為Object基類中的方法,呼叫時亦需要捕獲異常,以下為wait()可能丟擲的異常:

PS:能用圖說明的問題,我們就用圖來說明,能用表說明的問題,我們就用表來說明,這樣理解起來非常清晰。