一起學併發編程 - sleep與wait的差異

在JAVA的學習中,不少人會把sleepwait搞混,認爲都是做線程的等待,下面主要介紹下這倆者是什麼,及瞭解它們之間的差異和相似之處。

一般差異

簡單來說,wait()是一個用於線程同步的實例方法。它可以在任何對象上調用,因爲它定義在java.lang.Object上, 但只能從同步塊中調用。它釋放對象上的鎖,以便另一個線程可以跳入並獲取鎖。
另一方面,Thread.sleep()是可以從任何上下文調用的靜態方法。Thread.sleep()暫停當前​​線程,不釋放任何鎖。

主要區別

  • sleep()線程控制自身流程。wait()用來線程間通信,使擁有該對象鎖的線程等待直到指定時間或notify()。
  • wait()會釋放鎖和監視器,sleep()不釋放任何鎖或監視器等。wait()用於線程間通信,而sleep()用於在執行時引入暫停
  • 適用區域,wait只能放在同步語句塊中才有意義。

注意事項

wait可以代替sleep嗎?

不可以,如果直接調用wait會拋出java.lang.IllegalMonitorStateException異常,原因是還沒有得到對象鎖,所以無法釋放鎖。

如何獲取鎖?

  • 執行對象的synchronized實例方法。
  • 執行對象對應類的synchronized靜態方法。
  • 執行對該對象加synchronized的同步代碼塊。

演示

Thread.sleep

static void method1() {
    synchronized (LOCK) {
        try {
            System.out.println("[" + Thread.currentThread().getName() + "] begin sleep ...");
            Thread.sleep(5_000);
            System.out.println("[" + Thread.currentThread().getName() + "] end sleep ...");
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
    }
}

public static void main(String[] args) {
    Stream.of("T1", "T2").forEach(name -> new Thread(DifferenceOfWaitAndSleep::method1, name).start());
}

運行此示例一共將一共耗時10S,因T1線程獲得鎖後會暫停執行,這時候LOCK依舊在T1線程中,然後纔會被T2線程獲取

[T1] begin sleep ...
[T1] end sleep ...
[T2] begin sleep ...
[T2] end sleep ...

Object.wait

static void method2() {
    synchronized (LOCK) {
        try {
            System.out.println("[" + Thread.currentThread().getName() + "] begin wait ...");
            LOCK.wait();
            System.out.println("[" + Thread.currentThread().getName() + "] end wait ...");
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
    }
}

public static void main(String[] args) {
    Stream.of("T1", "T2").forEach(name -> new Thread(DifferenceOfWaitAndSleep::method2, name).start());
}

運行此示例會立即輸出T1/T2 begin wait ... 但永遠不會輸出T1/T2 end wait ...,因爲沒有線程調用LOCK.notify/notifyAll將它們喚醒

[T1] begin wait ...
[T2] begin wait ...

結論

調用:

wait(): 對象調用,當前線程必須在持有鎖的對象上進行同步。
sleep(): 線程調用,始終執行的當前線程

同步:

wait(): 同步多個線程同時訪問一個對象時
sleep(): 多個線程同步等待線程休眠

鎖:

wait(): 釋放鎖,其它線程有機會執行
sleep(): 持有鎖,固定時間後釋放或被打斷(interrupt)

喚醒條件:

wait(): 直到調用對象的 notify、notifyAll
sleep(): 直到至少時間到期或者調用interrupt()

使用:

sleep(): 用於時間同步
wait(): 用於多線程同步

- 說點什麼

全文代碼:https://gitee.com/battcn/battcn-concurent/tree/master/Chapter1-1/battcn-thread/src/main/java/com/battcn/chapter8

  • 個人QQ:1837307557
  • battcn開源羣(適合新手):391619659

微信公衆號:battcn(歡迎調戲)

發佈了60 篇原創文章 · 獲贊 19 · 訪問量 10萬+
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章