java中線程的sleep()方法和yield()方法的區(qū)別
1. sleep()方法
1.1 sleep()方法的定義
sleep()
方法是Thread
類的一個靜態(tài)方法,用于使當前線程進入休眠狀態(tài)(阻塞狀態(tài))一段指定的時間。在此期間,線程會暫停執(zhí)行并讓出CPU資源給其他線程。休眠時間結束后,線程會自動從休眠狀態(tài)恢復到可運行狀態(tài)(Runnable),等待操作系統(tǒng)重新調(diào)度。
sleep()
方法有兩個重載版本:
public static void sleep(long millis) throws InterruptedException; public static void sleep(long millis, int nanos) throws InterruptedException;
- 第一個方法使線程休眠指定的毫秒數(shù)。
- 第二個方法使線程休眠指定的毫秒數(shù)和額外的納秒數(shù)。
1.2 sleep()方法的工作原理
當線程調(diào)用Thread.sleep()
時,當前線程會進入阻塞狀態(tài),釋放CPU資源,其他線程可以利用這個時間片執(zhí)行。sleep()
方法不會釋放鎖或監(jiān)視器,即如果線程在同步塊或方法內(nèi)調(diào)用sleep()
,它仍然持有鎖。
sleep()
方法可以拋出InterruptedException
,這意味著如果線程在休眠期間被中斷,sleep()
會拋出此異常。因此,調(diào)用sleep()
時通常需要處理這個異常。
1.3 sleep()方法的應用場景
- 限速操作:當需要控制某些操作的執(zhí)行頻率時,可以使用
sleep()
方法。例如,在游戲循環(huán)中控制幀率,或者在網(wǎng)絡請求中限制請求的發(fā)送頻率。 - 等待條件:在某些場景下,線程可能需要等待一段時間后再重新檢查某個條件,這時可以使用
sleep()
來實現(xiàn)。 - 模擬延遲:
sleep()
可以用于模擬任務的執(zhí)行延遲,以便在測試和調(diào)試中更好地模擬真實的執(zhí)行環(huán)境。
1.4 sleep()方法的示例
public class SleepExample { public static void main(String[] args) { Thread thread = new Thread(() -> { System.out.println("Thread is going to sleep..."); try { Thread.sleep(2000); // 線程休眠2秒 } catch (InterruptedException e) { e.printStackTrace(); } System.out.println("Thread is awake!"); }); thread.start(); } }
在這個示例中,線程在啟動后進入休眠狀態(tài)2秒鐘,然后繼續(xù)執(zhí)行剩余的代碼。
2. yield()方法
2.1 yield()方法的定義
yield()
方法是Thread
類的另一個靜態(tài)方法,用于提示線程調(diào)度器當前線程愿意讓出CPU資源,以便讓其他同優(yōu)先級或更高優(yōu)先級的線程獲得執(zhí)行機會。yield()
方法的調(diào)用并不保證當前線程會立刻讓出CPU資源,也不保證其他線程會獲得執(zhí)行機會,這完全取決于線程調(diào)度器的實現(xiàn)和當前的系統(tǒng)負載。
public static native void yield();
2.2 yield()方法的工作原理
當線程調(diào)用Thread.yield()
時,線程調(diào)度器會檢查是否有其他同優(yōu)先級或更高優(yōu)先級的線程處于可運行狀態(tài)(Runnable)。如果有,它們將獲得執(zhí)行機會;如果沒有,當前線程可能繼續(xù)運行。因此,yield()
的作用類似于告訴調(diào)度器:“我現(xiàn)在已經(jīng)完成了一些工作,你可以選擇讓其他線程執(zhí)行。”
yield()
方法不會阻塞線程,線程僅僅是從“運行狀態(tài)”(Running)進入“可運行狀態(tài)”(Runnable),以便讓其他線程有機會運行。
2.3 yield()方法的應用場景
- 調(diào)試和測試:在調(diào)試和測試多線程應用程序時,
yield()
可以幫助模擬和驗證線程調(diào)度行為。 - 減輕競爭:在某些競爭條件較高的場景中,
yield()
可以用于提示線程調(diào)度器切換到其他線程,減輕線程之間的競爭。 - 協(xié)作式多任務處理:雖然現(xiàn)代操作系統(tǒng)多采用搶占式調(diào)度,但在某些情況下,
yield()
可以幫助實現(xiàn)一種類似協(xié)作式調(diào)度的效果,特別是在多線程計算密集型任務中。
2.4 yield()方法的示例
public class YieldExample { public static void main(String[] args) { Runnable task1 = () -> { for (int i = 0; i < 5; i++) { System.out.println("Task 1 - " + i); Thread.yield(); // 提示調(diào)度器讓出CPU } }; Runnable task2 = () -> { for (int i = 0; i < 5; i++) { System.out.println("Task 2 - " + i); Thread.yield(); // 提示調(diào)度器讓出CPU } }; Thread thread1 = new Thread(task1); Thread thread2 = new Thread(task2); thread1.start(); thread2.start(); } }
在這個示例中,兩個線程交替運行,每個線程在完成一次循環(huán)后調(diào)用yield()
,提示調(diào)度器將CPU時間分配給其他線程。
3. sleep()和 yield()的區(qū)別
3.1 目的不同
sleep()
:sleep()
的主要目的是使線程進入休眠狀態(tài)一段時間,從而暫停執(zhí)行并釋放CPU資源。在這段時間內(nèi),線程不參與競爭,也不消耗CPU資源,直到休眠時間結束或被中斷。yield()
:yield()
的目的是提示線程調(diào)度器當前線程愿意讓出CPU資源,使其他同優(yōu)先級或更高優(yōu)先級的線程有機會執(zhí)行。yield()
并不保證當前線程會被掛起,它只是表明當前線程愿意短暫地讓出CPU時間片。
3.2 行為不同
sleep()
:sleep()
是明確的時間控制,線程在調(diào)用sleep()
后會休眠指定的時間。在這段時間內(nèi),線程不會執(zhí)行任何操作,并且該線程必須等待時間結束后才能繼續(xù)執(zhí)行。yield()
:yield()
沒有時間控制,它只是將當前線程從“運行狀態(tài)”切換到“可運行狀態(tài)”。它并不一定會導致線程讓出CPU時間片,調(diào)度器可能讓當前線程繼續(xù)運行,也可能選擇其他線程。
3.3 對線程狀態(tài)的影響
sleep()
:調(diào)用sleep()
會使線程進入“阻塞狀態(tài)”(Blocked),直到指定的時間到達或被中斷。yield()
:調(diào)用yield()
不會使線程進入阻塞狀態(tài),線程仍然處于“可運行狀態(tài)”(Runnable),只是在等待調(diào)度器的重新調(diào)度。
3.4 是否釋放鎖
sleep()
:sleep()
不會釋放線程持有的任何鎖,即使線程在同步塊內(nèi)調(diào)用sleep()
,鎖仍然會被持有,其他線程無法獲取該鎖。yield()
:yield()
也不會釋放鎖。線程在調(diào)用yield()
時仍然持有所有鎖,這意味著即使線程短暫讓出CPU,其他線程也無法進入該線程所持有的同步塊。
3.5 拋出異常的情況
sleep()
:sleep()
可能會拋出InterruptedException
,如果線程在休眠期間被其他線程中斷,必須處理這個異常。yield()
:yield()
不會拋出InterruptedException
或任何其他異常。
3.6 實際使用效果
sleep()
:適用于需要明確暫停執(zhí)行的場景,如限速、等待條件等。sleep()
確保線程在指定的時間內(nèi)不執(zhí)行任何任務,并讓出CPU資源。yield()
:適用于想要讓調(diào)度器考慮切換到其他線程執(zhí)行的場景。yield()
的效果取決于線程調(diào)度器的實現(xiàn),不保證一定會切換到其他線程。
4. sleep()和 yield()的應用場景總結
4.1 sleep()的應用場景
- 實現(xiàn)定時任務:在定時任務中,
sleep()
可以用來使線程等待指定時間,然后繼續(xù)執(zhí)行任務。 - 限速處理:在網(wǎng)絡請求、數(shù)據(jù)處理等場景中,
sleep()
可以用來控制執(zhí)行頻率,防止系統(tǒng)過載。 - 模擬延遲:在測試中,
sleep()
可以用來模擬任務
的延遲執(zhí)行,以便驗證程序的行為。
4.2 yield()的應用場景
- 調(diào)試和測試:
yield()
可以幫助調(diào)試多線程程序,檢查線程調(diào)度行為,尤其是在競爭條件較高的情況下。 - 減輕競爭:在高競爭場景中,
yield()
可以提示調(diào)度器切換到其他線程,從而減少資源競爭的激烈程度。 - 優(yōu)化并發(fā)性能:在某些計算密集型任務中,
yield()
可以幫助實現(xiàn)更公平的調(diào)度,避免某些線程長時間占用CPU。
5. 結束語
sleep()
和yield()
是Java多線程編程中的兩個重要方法,盡管它們都可以控制線程的執(zhí)行順序和時間,但它們的作用和應用場景有顯著的區(qū)別。sleep()
用于明確的時間控制,讓線程進入休眠狀態(tài),并讓出CPU資源;而yield()
用于提示調(diào)度器當前線程愿意讓出CPU,但不保證會讓出。
在實際開發(fā)中,合理使用sleep()
和yield()
,可以有效地控制線程的執(zhí)行順序,優(yōu)化并發(fā)程序的性能,避免不必要的資源競爭。
到此這篇關于java中線程的sleep()方法和yield()方法的區(qū)別的文章就介紹到這了,更多相關java sleep()和yield()內(nèi)容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關文章希望大家以后多多支持腳本之家!
相關文章
Spring動態(tài)管理定時任務之ThreadPoolTaskScheduler解讀
這篇文章主要介紹了Spring動態(tài)管理定時任務之ThreadPoolTaskScheduler解讀,具有很好的參考價值,希望對大家有所幫助。如有錯誤或未考慮完全的地方,望不吝賜教2022-12-12spring boot+mybatis搭建一個后端restfull服務的實例詳解
這篇文章主要介紹了spring boot+mybatis搭建一個后端restfull服務,本文通過實例代碼給大家介紹的非常詳細,對大家的學習或工作具有一定的參考借鑒價值,需要的朋友可以參考下2020-11-11