多線程中sleep和wait的區別


前幾天去UC筆試,有一道簡答題問到了。之前還真一直沒留意到這個問題,所以答得也不好。

無論學習什么都好,通過對比學習更有利於發現事物的共性和個性,對於知識點的理解更有明顯效果(這也可能是UC筆試題上,5道簡答題中,有4道都是關於X與Y的區別的問題的原因之一)。

既然自己答得不好,那就寫下這篇隨筆,來警示下自己(不僅是sleep與wait區別,還有多用這種對比學習的學習方式)。

翻了很多資料,說的最多的一句就是,

  sleep與wait最主要的區別在於,sleep與wait都可以使線程等待,但sleep不會釋放資源而wait會釋放資源。

還有就是,wait方法只能在同步塊或者同步方法中執行。

  怎么理解這句話?

  這里有個例子:我登錄圖書管理系統訂了一本 《瘋狂JAVA講義》,當我去到圖書管排隊借書,到了借書窗口的時候,我告訴管理員我們的名字和預定的書,然后管理員查詢到我預訂的信息,然后安排助理去預定的圖書中找這本書,這個時候,如果我用的是sleep模式,我就一直站在窗口前,直到管理員給我這本書。如果我用的是wait模式,那么我就讓出位置給在排隊的后面的同學,到旁邊的椅子上等待,直到通知我,我要的書找到了,我再回到隊伍中排隊取票。

  這樣是不是明白對了?

下面來驗證一下,sleep是否不會釋放資源而wait會釋放資源。

public class ThreadTest {
    public static void main(String[] args) throws InterruptedException {
        
        new Thread(new Thread1()).start();
        
        synchronized (ThreadTest.class) {
            System.out.println("Main Thread go to sleep  : currenttime-->"+System.currentTimeMillis());
            //sleep過程不會釋放資源
            Thread.sleep(10000);
        }
        System.out.println("Main Thread get up : currenttime-->"+System.currentTimeMillis());
            new Thread(new Thread2()).start();
            System.out.println("Main Thread over");
    }
    static class Thread1 implements Runnable{
        @Override
        public void run() {
            System.out.println("Thread1 is ready :currenttime-->"+System.currentTimeMillis());
            //因為sleep不會釋放資源,所以在主線程sleep結束前,是不能取得資源的鎖,而是在等待
            synchronized (ThreadTest.class) {
            System.out.println("Thread1 is running :currenttime-->"+System.currentTimeMillis());
                System.out.println("Thread1 wait :currenttime-->"+System.currentTimeMillis());
                try {
                    ThreadTest.class.wait();
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }              
            System.out.println("Thread1 is over ");
        }
        }
        
    }
    static class Thread2 implements Runnable{
        @Override
        public void run() {
        System.out.println("Thread2 is ready :currenttime-->"+System.currentTimeMillis());
synchronized (ThreadTest.class){ System.out.println("Thread2 is running :currenttime-->"+System.currentTimeMillis()); System.out.println("Thread2 notify :currenttime-->"+System.currentTimeMillis()); ThreadTest.class.notify(); System.out.println("Thread2 is over"); } } } }

 

輸出結果:

Main Thread go to sleep  : currenttime-->1400232812969
Thread1 is ready :currenttime-->1400232812969
Main Thread get up : currenttime-->1400232822970
Thread1 is running :currenttime-->1400232822970
Thread1 wait :currenttime-->1400232822970
Main Thread over
Thread2 is ready :currenttime-->1400232822972
Thread2 is running :currenttime-->1400232822972
Thread2 notify :currenttime-->1400232822972
Thread2 is over
Thread1 is over

 

  由結果可以看出,當主線程sleep10s中的過程,Thread1僅僅處於ready狀態,而一直沒有獲取到ThreadTest.class的鎖,原因在於,主線程在sleep的之前已經獲取了該資源的鎖,這也驗證了在用sleep()的時候不會釋放資源。
   當主線程sleep完之后,Thread1獲取到了ThreadTest.class的鎖,然后調用了wait方法(wait方法是Object的靜態方法)。在調用該方法后,Thread2啟動,且順利獲取到ThreadTest.class的鎖,這也驗證了在用wait()方法的時候會釋放資源。

  最后,在Thread2中調用notify方法(notify方法也是Object的靜態方法,作用是喚醒在同步監視器上等待的一個線程),然后我們看到 "Thread1 is over"。wait 方法與 notify 方法或notifyAll方法 搭配使用,來協調線程運行。如果我們把Thread2中的notify方法去掉,會發現最后Thread1並沒有再次運行,也就不會打印"Thread1 is over"。

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM