通俗易懂的告訴你java多執行緒中wait和sleep的區別
在學習java多執行緒的過程中,我們能一定見過sleep和wait這兩個方法,這兩個方法都是多執行緒中經常使用的方法,並且它們都可以讓當前執行緒停下來。可是你知道嗎?這兩個方法其實有很大的差別。
01多執行緒的狀態
要想弄懂這兩個方法的差別,我們可以先簡單地看一下多執行緒的執行狀態
1. New:初始狀態,執行緒被建立,沒有呼叫start()
2. Runnable:執行狀態,Java執行緒把作業系統中的就緒和執行兩種狀態統一稱為“執行中”
3. Blocked:阻塞,執行緒進入等待狀態,執行緒因為某種原因,放棄了CPU的使用權
4. Waiting:等待狀態
5. timed_waiting:超時等待狀態,超時以後自動返回
6. terminated:終止狀態,當前執行緒執行完畢
這裡介紹多執行緒的幾個狀態,主要是想大家看下,在這幾個狀態的轉化中wait和sleep的作用。
通過上面的圖可以看到
wait使執行緒從Running到Waitingsleep使執行緒從Running到timed_waiting:超時等待狀態,時間一到自動變回Running狀態可以看出wait和sleep都可以使執行緒中止,但是也存在許多不同,下面就逐一來看下wait和sleep的不同之處
02區別
一、sleep是Thread的方法,wait是Object的方法
sleep的原始碼
可以看到sleep在Thread類中,並且是Thread的一個靜態本地方法,所以平時我們呼叫sleep的時候就Thread.sleep()這樣就可以進行呼叫了。
wait原始碼
可以看到wait方法在Object類中,因為java中所有的類都是繼承自object的,所以所有類都可以呼叫wait方法,這是一個final的方法,同時不是一個靜態方法,所以呼叫該方法需要先例項化一個Object物件才可以
二、sleep不會去釋放鎖,但是wait會釋放這個鎖,並把這個wait的執行緒加入到這個鎖的等待佇列中去
廢話少說看例子!
sleep不會釋放鎖
通過輸出結果我們可以看到,t1和t2這兩個執行緒是順序輸出的,因為sleep不會釋放鎖,必須等sleep結束了才會釋放鎖,下一個執行緒才能去執行。
wait會釋放鎖
通過這個輸出結果可以看到t1和t2這兩個執行緒幾乎是同時執行的,這是因為wait在中止執行緒的時候是直接把執行緒放到等待佇列中的,會直接釋放鎖
三、使用wait必須要定義一個synchronized,而sleep不需要
廢話少說,看例子!
看輸出結果可以發現,會報一個非法的監視器錯誤,這就是因為wait必須要在synchronized修飾的語句塊或者方法和類中
四、使用sleep不需要被喚醒,但是wait是需要notify()或者notifyAll()去喚醒的,除了wait(1000)這種形式
03總結
多執行緒的狀態變化還是比較複雜的,在這其中wait和sleep都能起到使執行緒中止的目的,但是它倆有很多區別,在實際的使用中要根據具體情況來定。同時“wait和sleep的區別”是很多面試官都喜歡問的,希望看完這篇文章對大家有幫助。