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

Java詳細分析sleep和wait方法有哪些區(qū)別

 更新時間:2022年04月26日 09:00:48   作者:淡沫初夏Zz  
這篇文章主要介紹了Java中wait與sleep的講解(wait有參及無參區(qū)別),通過代碼介紹了wait()?與wait(?long?timeout?)?區(qū)別,wait(0)?與?sleep(0)區(qū)別,需要的朋友可以參考下

一、sleep和wait方法的區(qū)別

  • 根本區(qū)別:sleep是Thread類中的方法,不會馬上進入運行狀態(tài),wait是Object類中的方法,一旦一個對象調用了wait方法,必須要采用notify()和notifyAll()方法喚醒該進程
  • 釋放同步鎖:sleep會釋放cpu,但是sleep不會釋放同步鎖的資源,wait會釋放同步鎖資源
  • 使用范圍: sleep可以在任何地方使用,但wait只能在synchronized的同步方法或是代碼塊中使用
  • 異常處理: sleep需要捕獲異常,而wait不需要捕獲異常

二、wait方法

  • 使當前執(zhí)行代碼的線程進行等待. (把線程放到等待隊列中)
  • 釋放當前的鎖
  • 滿足一定條件時被喚醒, 重新嘗試獲取這個鎖.
  • wait 要搭配 synchronized 來使用,脫離 synchronized 使用 wait 會直接拋出異常.

wait方法的使用

wait方法

/**
 * wait的使用
 */
public class WaitDemo1 {
    public static void main(String[] args) {
        Object lock = new Object();
        Thread t1 = new Thread(() -> {
            System.out.println("線程1開始執(zhí)行");
            try {
                synchronized (lock) {
                    System.out.println("線程1調用wait方法....");
                    // 無限期的等待狀態(tài)
                    lock.wait();
                }
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
            System.out.println("線程1執(zhí)行完成");
        }, "線程1");
        t1.start();
    }
}

有參wait線程和無參wait線程

/**
 * 有參wait線程和無參wait線程
 */
public class WaitDemo2 {
    public static void main(String[] args) {
        Object lock1 = new Object();
        Object lock2 = new Object();
        Thread t1 = new Thread(()->{
            System.out.println("線程1開始執(zhí)行");
            synchronized (lock1){
                try {
                    lock1.wait();
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
                System.out.println("線程1執(zhí)行完成");
            }
        },"無參wait線程");
        t1.start();
        Thread t2 = new Thread(()->{
            System.out.println("線程2開始執(zhí)行");
            synchronized (lock2){
                try {
                    lock2.wait(60*60*1000);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
                System.out.println("線程2執(zhí)行完成");
            }
        },"有參wait線程");
        t2.start();
    }
}

wait結束等待的條件

①其他線程調用該對象的 notify 方法.

②wait 等待時間超時 (wait 方法提供一個帶有 timeout 參數(shù)的版本, 來指定等待時間).

③其他線程調用該等待線程的 interrupted 方法, 導致 wait 拋出 InterruptedException 異常

三、notify和notifyAll方法

notify 方法只是喚醒某一個等待的線程

  1. 方法notify()也要在同步方法或同步塊中調用,該方法是用來通知那些可能等待該對象的對象鎖的其它線程
  2. 如果有多個線程等待,隨機挑選一個wait狀態(tài)的線程
  3. 在notify()方法后,當前線程不會馬上釋放該對象鎖,要等到執(zhí)行notify()方法的線程將程序執(zhí)行完,也就是退出同步代碼塊之后才會釋放對象鎖

notify方法的使用

/**
 * wait的使用, 如果有多個線程等待,隨機挑選一個wait狀態(tài)的線程
 */
public class WaitNotifyDemo {
    public static void main(String[] args) {
        Object lock1 = new Object();
        Object lock2 = new Object();
        Thread t1 = new Thread(()->{
            System.out.println("線程1開始執(zhí)行");
            try {
                synchronized (lock1) {
                    System.out.println("線程1調用wait方法");
                    lock1.wait();
                }
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
            System.out.println("線程1執(zhí)行完成");
        },"線程1");
        Thread t2 = new Thread(()->{
            System.out.println("線程2開始執(zhí)行");
            try {
                synchronized (lock1) {
                    System.out.println("線程2調用wait方法");
                    lock1.wait();
                }
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
            System.out.println("線程2執(zhí)行完成");
        },"線程2");
        t1.start();
        t2.start();
        // 喚醒 lock1 對象上休眠的線程的(隨機喚醒一個)
        Thread t3 = new Thread(()->{
            try {
                Thread.sleep(1500);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
            System.out.println("線程3開始執(zhí)行");
            synchronized (lock1){
                //發(fā)出喚醒通知
                System.out.println("執(zhí)行了喚醒");
                try {
                    Thread.sleep(2000);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
            }
        },"線程3");
        t3.start();
    }
}

notifyAll方法可以一次喚醒所有的等待線程

notifyAll方法的使用

/**
 * notifyAll-喚醒所有線程
 */
public class WaitNotifyAll {
    public static void main(String[] args) {
        Object lock = new Object();

        new Thread(() -> {
            System.out.println("線程1:開始執(zhí)行");
            synchronized (lock) {
                try {
                    lock.wait();
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
                System.out.println("線程1:執(zhí)行完成");
            }
        }, "無參wait線程").start();

        new Thread(() -> {
            synchronized (lock) {
                System.out.println("線程2:開始執(zhí)行 |" + LocalDateTime.now());
                try {
                    lock.wait(60 * 60 * 60 * 1000);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
                System.out.println("線程2:執(zhí)行完成 | " + LocalDateTime.now());
            }
        }, "有參wait線程").start();

        new Thread(() -> {
            try {
                TimeUnit.SECONDS.sleep(1);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
            synchronized (lock) {
                System.out.println("喚醒所有線程");
                lock.notifyAll();
            }
        }).start();
    }
}

notify和notifyAll方法的區(qū)別

  1. 當你調用notify時,只有一個等待線程會被喚醒而且它不能保證哪個線程會被喚醒,這取決于線程調度器。
  2. 調用notifyAll方法,那么等待該鎖的所有線程都會被喚醒,但是在執(zhí)行剩余的代碼之前,所有被喚醒的線程都將爭奪鎖定,這就是為什么在循環(huán)上調用wait,因為如果多個線程被喚醒,那么線程是將獲得鎖定將首先執(zhí)行,它可能會重置等待條件,這將迫使后續(xù)線程等待。
  3. 因此,notify和notifyAll之間的關鍵區(qū)別在于notify()只會喚醒一個線程,而notifyAll方法將喚醒所有線程。

到此這篇關于Java詳細分析sleep和wait方法有哪些區(qū)別的文章就介紹到這了,更多相關Java sleep與wait內(nèi)容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關文章希望大家以后多多支持腳本之家!

相關文章

  • Spring中@PathVariable注解的簡單使用

    Spring中@PathVariable注解的簡單使用

    這篇文章主要介紹了Spring中@PathVariable注解的簡單使用,@PathVariable 是 Spring Framework 中的注解之一,用于處理 RESTful Web 服務中的 URL 路徑參數(shù),它的作用是將 URL 中的路徑變量綁定到方法的參數(shù)上,需要的朋友可以參考下
    2024-01-01
  • 基于SpringBoot+Redis的Session共享與單點登錄詳解

    基于SpringBoot+Redis的Session共享與單點登錄詳解

    這篇文章主要介紹了基于SpringBoot+Redis的Session共享與單點登錄,文中通過示例代碼介紹的非常詳細,對大家的學習或者工作具有一定的參考學習價值,需要的朋友可以參考下
    2019-07-07
  • SpringBoot通過Nginx代理獲取真實IP

    SpringBoot通過Nginx代理獲取真實IP

    springboot作為后臺代碼,獲取到的登錄IP是前臺的代理服務器地址,并不是用戶的真實IP地址,本文主要介紹了SpringBoot通過Nginx代理獲取真實IP,具有一定的參考價值,感興趣的可以了解一下
    2024-01-01
  • MyBatis?實現(xiàn)多對多中間表插入數(shù)據(jù)

    MyBatis?實現(xiàn)多對多中間表插入數(shù)據(jù)

    這篇文章主要介紹了MyBatis?實現(xiàn)多對多中間表插入數(shù)據(jù),具有很好的參考價值,希望對大家有所幫助。如有錯誤或未考慮完全的地方,望不吝賜教
    2022-02-02
  • 詳解SpringBoot中的統(tǒng)一結果返回與統(tǒng)一異常處理

    詳解SpringBoot中的統(tǒng)一結果返回與統(tǒng)一異常處理

    這篇文章主要將通過詳細的討論和實例演示來幫助你更好地理解和應用Spring Boot中的統(tǒng)一結果返回和統(tǒng)一異常處理,感興趣的小伙伴可以了解下
    2024-03-03
  • SpingMvc復雜參數(shù)傳收總結

    SpingMvc復雜參數(shù)傳收總結

    這篇文章主要為大家介紹了SpingMvc復雜參數(shù)傳收總結,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進步,早日升職加薪
    2023-08-08
  • spring cloud config 配置中心快速實現(xiàn)過程解析

    spring cloud config 配置中心快速實現(xiàn)過程解析

    這篇文章主要介紹了spring cloud config 配置中心快速實現(xiàn)過程解析,文中通過示例代碼介紹的非常詳細,對大家的學習或者工作具有一定的參考學習價值,需要的朋友可以參考下
    2019-08-08
  • Spring Boot集成MyBatis訪問數(shù)據(jù)庫的方法

    Spring Boot集成MyBatis訪問數(shù)據(jù)庫的方法

    這篇文章主要介紹了Spring Boot集成MyBatis訪問數(shù)據(jù)庫的方法,需要的朋友可以參考下
    2017-04-04
  • SpringBoot中使用@Value注解注入詳解

    SpringBoot中使用@Value注解注入詳解

    這篇文章主要介紹了SpringBoot中的@Value注入詳解,在SpringBoot中,@Value注解可以注入一些字段的普通屬性,并且會自動進行類型轉換,本文對這些類型進行總結,需要的朋友可以參考下
    2023-08-08
  • MyBatis-Plus 修改和添加自動填充時間方式

    MyBatis-Plus 修改和添加自動填充時間方式

    這篇文章主要介紹了MyBatis-Plus 修改和添加自動填充時間方式,具有很好的參考價值,希望對大家有所幫助。如有錯誤或未考慮完全的地方,望不吝賜教
    2021-08-08

最新評論