亚洲乱码中文字幕综合,中国熟女仑乱hd,亚洲精品乱拍国产一区二区三区,一本大道卡一卡二卡三乱码全集资源,又粗又黄又硬又爽的免费视频

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

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

前言

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

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

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

wait()

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

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

 通過(guò)wait方法的注釋?zhuān)覀兛梢园l(fā)現(xiàn),wait方法有如下作用:

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

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

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

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

通過(guò)JDK源碼的注釋?zhuān)覀儗?duì)wait和notify方法有了更進(jìn)一步的了解,那么接著看看sleep方法,才能知道wait和sleep的區(qū)別

sleep()

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

來(lái)看看它們的注釋?zhuān)?/p>

/*
根據(jù)系統(tǒng)計(jì)時(shí)器和調(diào)度程序的精度和準(zhǔn)確性,使當(dāng)前執(zhí)行的線(xiàn)程休眠(暫時(shí)停止執(zhí)行)指定的毫秒數(shù)
線(xiàn)程不會(huì)釋放持有的鎖
該方法響應(yīng)中斷,當(dāng)遇到中斷時(shí)會(huì)拋出InterruptedException異常,并且會(huì)清除當(dāng)前線(xiàn)程的中斷狀態(tài)
*/
public static native void sleep(long millis) throws InterruptedException;
/*
使當(dāng)前執(zhí)行的線(xiàn)程休眠(臨時(shí)停止執(zhí)行)指定的毫秒數(shù)加上指定的納秒數(shù),具體取決于系統(tǒng)計(jì)時(shí)器和調(diào)度程序的精度和準(zhǔn)確性
線(xià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)前線(xiàn)程休眠,時(shí)間一到當(dāng)前線(xiàn)程繼續(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í)間一到,無(wú)需其他線(xiàn)程喚醒,也會(huì)重新競(jìng)爭(zhēng)獲取對(duì)象的鎖繼續(xù)執(zhí)行。

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

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

區(qū)別3:所屬類(lèi)

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

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)前線(xiàn)程休眠,不涉及到對(duì)象類(lèi),也不需要獲得對(duì)象的鎖,所以是線(xiàn)程類(lèi)的方法。wait 是讓獲得對(duì)象鎖的線(xiàn)程實(shí)現(xiàn)等待,前提是要楚獲得對(duì)象的鎖,所以是類(lèi)的方法。

區(qū)別4:釋放鎖

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

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

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

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

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

相關(guān)文章

最新評(píng)論