Java Thread(線程) 詳解sleep和wait的區別



sleep()方法
  sleep()使當前線程進入停滯狀態(阻塞當前線程),讓出CUP的使用、目的是不讓當前線程獨自霸佔該進程所獲的CPU資源,以留一定時間給其他線程執行的機會;
   sleep()是Thread類的Static(靜態)的方法;因此他不能改變對象的機鎖,所以當在一個Synchronized塊中調用Sleep()方法是,線程雖然休眠了,但是對象的機鎖並木有被釋放,其他線程無法訪問這個對象(即使睡着也持有對象鎖)。
  在sleep()休眠時間期滿後,該線程不一定會立即執行,這是因爲其它線程可能正在運行而且沒有被調度爲放棄執行,除非此線程具有更高的優先級。 
   
wait()方法
  wait()方法是Object類裏的方法;當一個線程執行到wait()方法時,它就進入到一個和該對象相關的等待池中,同時失去(釋放)了對象的機鎖(暫時失去機鎖,wait(long timeout)超時時間到後還需要返還對象鎖);其他線程可以訪問;
  wait()使用notify或者notifyAlll或者指定睡眠時間來喚醒當前等待池中的線程。
  wiat()必須放在synchronized block中,否則會在program runtime時扔出”java.lang.IllegalMonitorStateException“異常。


 
  所以sleep()和wait()方法的最大區別是:
    sleep()睡眠時,保持對象鎖,仍然佔有該鎖;
    而wait()睡眠時,釋放對象鎖。
  但是wait()和sleep()都可以通過interrupt()方法打斷線程的暫停狀態,從而使線程立刻拋出InterruptedException(但不建議使用該方法)。
/**
 * Thread sleep和wait區別
 * @author DreamSea 
 * 2012-1-15
 */
public class ThreadTest implements Runnable {
    int number = 10;

    public void firstMethod() throws Exception {
        synchronized (this) {
            number += 100;
            System.out.println(number);
        }
    }

    public void secondMethod() throws Exception {
        synchronized (this) {
            /**
             * (休息2S,阻塞線程)
             * 以驗證當前線程對象的機鎖被佔用時,
             * 是否被可以訪問其他同步代碼塊
             */
            Thread.sleep(2000);
            //this.wait(2000);
            number *= 200;
        }
    }

    @Override
    public void run() {
        try {
            firstMethod();
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

    public static void main(String[] args) throws Exception {
        ThreadTest threadTest = new ThreadTest();
        Thread thread = new Thread(threadTest);
        thread.start();
        threadTest.secondMethod();
    }
}



使用Sleep()方法輸出結果:【顯示輸出】
使用Sleep()方法輸出結果
使用Wait()方法輸出結果:【顯示輸出】
使用wait()方法輸出結果

我們來大致分析一下此段代碼,main()方法中實例化ThreadTest並啓動該線程,然後調用該線程的一個方法(secondMethod()),因爲在主線程中調用方法,所以調用的普通方法secondMethod())會先被執行(但並不是普通方法執行完畢該對象的線程方法才執行,普通方法執行過程中,該線程的方法也會被執行,他們是交替執行的,只是在主線程的普通方法會先被執行而已),所以程序運行時會先執行secondMethod(),而secondMethod()方法代碼片段中有synchronized block,因此secondMethod方法被執行後,該方法會佔有該對象機鎖導致該對象的線程方法一直處於阻塞狀態,不能執行,直到secondeMethod釋放鎖;
使用Thread.sleep(2000)方法時,因爲sleep在阻塞線程的同時,並持有該對象鎖,所以該對象的其他同步線程(secondMethod())無法執行,直到synchronized block執行完畢(sleep休眠完畢),secondMethod()方法纔可以執行,因此輸出結果爲number*200+100;
使用this.wait(2000)方法時,secondMethod()方法被執行後也鎖定了該對象的機鎖,執行到this.wait(2000)時,該方法會休眠2S並釋當前持有的鎖,此時該線程的同步方法會被執行(因爲secondMethod持有的鎖,已經被wait()所釋放),因此輸出的結果爲:number+100;
【顯示流程】 
sleep()和wait()方法的區別已經講解完畢,若對線程有興趣的童鞋我在諾諾的問問:在main方法中最後行加入“System.out.println("number="+threadTest.number);”猜猜會輸出什麼結果。。。J

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章