欧美bbbwbbbw肥妇,免费乱码人妻系列日韩,一级黄片

Java多線程中sleep和wait區(qū)別

 更新時(shí)間:2023年06月06日 10:54:15   作者:逆流°只是風(fēng)景-bjhxcc  
本文主要介紹了Java多線程中sleep和wait區(qū)別,文中通過示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧

前言

sleep(休眠) 和 wait(等待) 方法是 Java 多線程中常用的兩個(gè)方法,它們有什么區(qū)別及一些該注意的地方有哪些呢?下面給大家一一分解。

sleep和wait方法都是native關(guān)鍵字修飾的方法,這說明這兩個(gè)方法是原生函數(shù),也就是由C/C++實(shí)現(xiàn)的,那么我們就暫時(shí)不關(guān)心它的具體實(shí)現(xiàn)了。

sleep方法是Thread類中的方法,而wait方法是Object中的方法,那么我們首先看看wait方法。

wait()

從Object源碼中,我們可以發(fā)現(xiàn),wait有三個(gè)重載方法,分別是無參的wait方法,帶有l(wèi)ong和int類型參數(shù)的的wait方法,以及帶有l(wèi)ong類型參數(shù)的方法。其實(shí)前兩個(gè)方法最終都是調(diào)用了wait(long)方法,而wait(long)方法是native修飾的方法,它底層就是由C++實(shí)現(xiàn)的,這里暫且不討論,我們來看看這個(gè)方法的注釋。

/*
wait方法會(huì)導(dǎo)致當(dāng)前線程等待,直到其他線程調(diào)用notify和notifyAll方法,或者達(dá)到了指定的等待時(shí)間
使用wait方法的前提是當(dāng)前線程擁有該對(duì)象的監(jiān)視器也就是鎖
該方法會(huì)導(dǎo)致當(dāng)前線程T(調(diào)用wait方法的線程)將自己放到該對(duì)象的等待集合中,然后會(huì)放棄此對(duì)象上的所有同步聲明,也就是會(huì)放棄對(duì)象的鎖
該等待線程不會(huì)被調(diào)度并且處于休眠狀態(tài),直到以下四種情況之一發(fā)生:
1、其他線程調(diào)用等待對(duì)象notify方法,并且當(dāng)前線程T被隨機(jī)選為要喚醒的方法時(shí),線程將會(huì)退出休眠狀態(tài)
2、其他線程調(diào)用等待對(duì)象的notifyAll方法
3、其他線程中斷當(dāng)前線程T
4、超過指定的等待時(shí)間。如果等待時(shí)間為0的話,時(shí)間因素將不會(huì)被考慮,那線程將等待直到被通知喚醒
當(dāng)發(fā)生上述四種情況時(shí),線程T將會(huì)從該對(duì)象的等待集合中移除,并且可以重新被調(diào)度。然后它以通常的方式與其他線程競(jìng)爭(zhēng)對(duì)象上的同步鎖,一旦它獲得了對(duì)對(duì)象的控制權(quán),它對(duì)對(duì)象的所有同步聲明將會(huì)恢復(fù)到原來的狀態(tài),也就是說,恢復(fù)到調(diào)用wait方法時(shí)的狀態(tài)。然后線程T將會(huì)從調(diào)用wait方法的方法中返回。因此,從wait方法返回時(shí),對(duì)象和線程T的同步狀態(tài)與調(diào)用wait方法時(shí)的狀態(tài)完全相同。
如果當(dāng)前線程在等待之前或者等待時(shí)被中斷,會(huì)拋出InterruptedException異常。
注意,等待方法將當(dāng)前線程防止到該對(duì)象的等待集合時(shí),只解鎖此對(duì)象;在線程等待時(shí),當(dāng)前線程同步的其他任何對(duì)象都將保持鎖定狀態(tài)。
wait方法僅能被持有對(duì)象監(jiān)視器的線程調(diào)用(對(duì)象監(jiān)視器就相當(dāng)于對(duì)象的鎖)
通過如下方法可以獲得對(duì)象的監(jiān)視器:
1、通過執(zhí)行該對(duì)象的同步方法(也就是synchronized關(guān)鍵字修飾的方法)
2、通過執(zhí)行該對(duì)象的同步代碼塊(synchronized(Object) {})
3、通過執(zhí)行類的同步靜態(tài)代碼塊(也就是synchronized關(guān)鍵字修飾的靜態(tài)方法)
*/
public final native void wait(long timeout) throws InterruptedException;

 通過wait方法的注釋,我們可以發(fā)現(xiàn),wait方法有如下作用:

  • 使線程進(jìn)入休眠狀態(tài),不被調(diào)度,直到被notify方法選中或者notifyAll方法的執(zhí)行,才會(huì)被喚醒
  • 線程會(huì)釋放調(diào)用wait方法的對(duì)象的鎖(但是不會(huì)釋放線程持有的其他對(duì)象的鎖),這樣其他線程可以競(jìng)爭(zhēng)該對(duì)象的鎖
  • 從wait方法中退出后,線程會(huì)回到調(diào)用該方法時(shí)的狀態(tài)

既然要notify和notifyAll方法才能喚醒調(diào)用wait方法陷入等待的線程,那么我們看看這兩個(gè)方法的注釋:

/*
喚醒一個(gè)等待對(duì)象鎖的線程
如果有多個(gè)線程在等待該對(duì)象,會(huì)隨機(jī)喚醒一個(gè)線程
在當(dāng)前線程放棄該對(duì)象的鎖之前,喚醒的線程將無法繼續(xù)執(zhí)行
喚醒的線程將以通常的方式與其他線程競(jìng)爭(zhēng),這些線程會(huì)公平地在這個(gè)對(duì)象上進(jìn)行同步競(jìng)爭(zhēng)。例如,被喚醒的線程在競(jìng)爭(zhēng)對(duì)象的鎖時(shí)沒有特權(quán)或者缺點(diǎn)
該方法僅在線程持有對(duì)象的監(jiān)視器時(shí)才能被調(diào)用,獲取對(duì)象的監(jiān)視器有如下方法:也就是synchronized關(guān)鍵字修飾的方法、靜態(tài)方法以及代碼塊等
*/
public final native void notify();
/*
喚醒所有等待該對(duì)象監(jiān)視器的線程
在當(dāng)前持有對(duì)象鎖的線程放棄對(duì)象鎖之前,被喚醒的線程無法執(zhí)行
*/
public final native void notifyAll();

通過方法的注釋來看,這兩個(gè)方法就是用于喚醒等待該對(duì)象的線程,notify隨機(jī)喚醒一個(gè)線程,notifyAll會(huì)喚醒全部線程,這些被喚醒的線程處于就緒態(tài),它們會(huì)和正在運(yùn)行的線程一起搶占對(duì)象的鎖,得到對(duì)象的鎖之后才能繼續(xù)執(zhí)行。

通過JDK源碼的注釋,我們對(duì)wait和notify方法有了更進(jìn)一步的了解,那么接著看看sleep方法,才能知道wait和sleep的區(qū)別

sleep()

Thread類中的sleep方法也有兩個(gè)重載方法,其中sleep(long)是底層的實(shí)現(xiàn)。

來看看它們的注釋:

/*
根據(jù)系統(tǒng)計(jì)時(shí)器和調(diào)度程序的精度和準(zhǔn)確性,使當(dāng)前執(zhí)行的線程休眠(暫時(shí)停止執(zhí)行)指定的毫秒數(shù)
線程不會(huì)釋放持有的鎖
該方法響應(yīng)中斷,當(dāng)遇到中斷時(shí)會(huì)拋出InterruptedException異常,并且會(huì)清除當(dāng)前線程的中斷狀態(tài)
*/
public static native void sleep(long millis) throws InterruptedException;
/*
使當(dāng)前執(zhí)行的線程休眠(臨時(shí)停止執(zhí)行)指定的毫秒數(shù)加上指定的納秒數(shù),具體取決于系統(tǒng)計(jì)時(shí)器和調(diào)度程序的精度和準(zhǔn)確性
線程不會(huì)釋放持有的鎖
nanos的范圍:0-999999
*/
public static void sleep(long millis, int nanos)
? ? throws InterruptedException {
? ? ?? ?// 判斷millis和nanos是否符合條件
? ? ? ? if (millis < 0) {
? ? ? ? ? ? throw new IllegalArgumentException("timeout value is negative");
? ? ? ? }
? ? ? ? if (nanos < 0 || nanos > 999999) {
? ? ? ? ? ? throw new IllegalArgumentException(
? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? "nanosecond timeout value out of range");
? ? ? ? }
? ? ? ? if (nanos >= 500000 || (nanos != 0 && millis == 0)) {
? ? ? ? ? ? millis++;
? ? ? ? }
?? ??? ?// 調(diào)用原生sleep方法
? ? ? ? sleep(millis);
? ? }

wait()和sleep()方法區(qū)別

區(qū)別1:使用限制

使用 sleep 方法可以讓讓當(dāng)前線程休眠,時(shí)間一到當(dāng)前線程繼續(xù)往下執(zhí)行,在任何地方都能使用,但需要捕獲 InterruptedException 異常。

try {
    Thread.sleep(3000L);
} catch (InterruptedException e) {
    e.printStackTrace();
}

而使用 wait 方法則必須放在 synchronized 塊里面,同樣需要捕獲 InterruptedException 異常,并且需要獲取對(duì)象的鎖。

synchronized (lock){
    try {
        lock.wait();
    } catch (InterruptedException e) {
        e.printStackTrace();
    }
}

而且 wait 還需要額外的方法 notify/ notifyAll 進(jìn)行喚醒,它們同樣需要放在 synchronized 塊里面,且獲取對(duì)象的鎖。。

synchronized (lock) {
? ? // 隨機(jī)喚醒
? ? lock.notify();
? ? // 喚醒全部
? ? lock.notifyAll();
}

當(dāng)然也可以使用帶時(shí)間的 wait(long millis) 方法,時(shí)間一到,無需其他線程喚醒,也會(huì)重新競(jìng)爭(zhēng)獲取對(duì)象的鎖繼續(xù)執(zhí)行。

區(qū)別2:使用場(chǎng)景

sleep 一般用于當(dāng)前線程休眠,或者輪循暫停操作,wait 則多用于多線程之間的通信。

區(qū)別3:所屬類

sleep 是 Thread 類的靜態(tài)本地方法,wait 則是 Object 類的本地方法。

java.lang.Thread#sleep

public static native void sleep(long millis) throws InterruptedException;

java.lang.Object#wait

public final native void wait(long timeout) throws InterruptedException;

為什么要這樣設(shè)計(jì)呢?

因?yàn)?sleep 是讓當(dāng)前線程休眠,不涉及到對(duì)象類,也不需要獲得對(duì)象的鎖,所以是線程類的方法。wait 是讓獲得對(duì)象鎖的線程實(shí)現(xiàn)等待,前提是要楚獲得對(duì)象的鎖,所以是類的方法。

區(qū)別4:釋放鎖

Object lock = new Object();
synchronized (lock) {
    try {
        lock.wait(3000L);
        Thread.sleep(2000L);
    } catch (InterruptedException e) {
        e.printStackTrace();
    }
}

如上代碼所示,wait 可以釋放當(dāng)前線程對(duì) lock 對(duì)象鎖的持有,而 sleep 則不會(huì)。

區(qū)別5:線程切換

sleep 會(huì)讓出 CPU 執(zhí)行時(shí)間且強(qiáng)制上下文切換,而 wait 則不一定,wait 后可能還是有機(jī)會(huì)重新競(jìng)爭(zhēng)到鎖繼續(xù)執(zhí)行的。

到此這篇關(guān)于Java多線程中sleep和 wait區(qū)別的文章就介紹到這了,更多相關(guān)Java sleep和wait內(nèi)容請(qǐng)搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!

相關(guān)文章

最新評(píng)論