JAVA線程sleep()和wait()

sleep

1.sleep是Thread的一個靜態(static)方法。使得Runnable實現的線程也可使用sleep方法。並且避免了線程以前相互調用sleep()方法,引起死鎖。java

2.sleep()執行時須要賦予一個沉睡時間。在沉睡期間(阻塞線程期間),CPU會放棄這個線程,執行其餘任務。當沉睡時間到了以後,該線程會自動甦醒,不過此時線程不會馬上被執行,而是要等CPU分配資源,和其餘線程進行競爭。併發

3.此外若是這個線程以前獲取了一個機鎖,在沉睡期間,這個機鎖不會釋放。其餘等待這個機鎖的程序,必須等待這個線程醒來,且執行完後才能運行。ide

sleep相關代碼

public class ThreadTest2 {

    public static void main(String[] args){
        System.out.println("begin our test");
        ThreadSleep sleep = new ThreadSleep();
        try {
            Thread thread1 = new Thread(sleep,"路人甲");
            Thread thread2 = new Thread(sleep,"路人乙");
            thread1.start();
            thread2.start();
        }catch(Exception e){
            e.printStackTrace();
        }
        System.out.println("test is over");
    }


}

 class ThreadSleep implements  Runnable{

     int count = 0;

     @Override
     public void run(){
         System.out.println(Thread.currentThread().getName() + " say : hello sleep !!");
         count();

     }

     public void count(){
         while(count < 20) {
                 System.out.println(Thread.currentThread().getName() + " say : count is " + count);
                 try {
                     count++;
                     Thread.sleep(100);
                 } catch (Exception e) {
                     e.printStackTrace();
                 }
         }

     }
}

輸出日誌this

begin our test
test is over
路人甲 say : hello sleep !!
路人甲 say : count is 0
路人乙 say : hello sleep !!
路人乙 say : count is 1
路人甲 say : count is 2
路人乙 say : count is 2
路人甲 say : count is 4
路人乙 say : count is 4
路人甲 say : count is 6
路人乙 say : count is 7
路人乙 say : count is 8
路人甲 say : count is 8
路人甲 say : count is 10
路人乙 say : count is 10
路人乙 say : count is 12
路人甲 say : count is 12
路人乙 say : count is 14
路人甲 say : count is 14
路人甲 say : count is 16
路人乙 say : count is 16
路人甲 say : count is 18
路人乙 say : count is 18

經過日誌能夠發現線程甲和線程乙基本是交替執行,可是並不規律,且出現了併發問題。spa

該狀況是因爲代碼中設置了睡眠時間爲100毫秒,因爲count遞增執行速度很快,因此線程差很少是同時睡眠,而後同時甦醒並致使了併發的出現。線程

接下來要添加synchronize塊,檢查sleep時機鎖是否釋放日誌

public class ThreadTest2 {

    public static void main(String[] args){
        System.out.println("begin our test");
        ThreadSleep sleep = new ThreadSleep();
        try {
            Thread thread1 = new Thread(sleep,"路人甲");
            Thread thread2 = new Thread(sleep,"路人乙");
            thread1.start();
            thread2.start();
        }catch(Exception e){
            e.printStackTrace();
        }
        System.out.println("test is over");
    }


}

class ThreadSleep implements  Runnable{

    int count = 0;

    @Override
    public void run(){
        System.out.println(Thread.currentThread().getName() + " say : hello sleep !!");
        count();

    }

    public void count(){
        while(count < 20) {
            synchronized (this) {
                System.out.println(Thread.currentThread().getName() + " say : count is " + count);
                try {
                    count++;
                    Thread.sleep(100);
                } catch (Exception e) {
                    e.printStackTrace();
                }

            }
        }

    }
}

輸出日誌code

begin our test
路人甲 say : hello sleep !!
路人甲 say : count is 0
test is over
路人乙 say : hello sleep !!
路人甲 say : count is 1
路人甲 say : count is 2
路人甲 say : count is 3
路人甲 say : count is 4
路人甲 say : count is 5
路人甲 say : count is 6
路人甲 say : count is 7
路人甲 say : count is 8
路人甲 say : count is 9
路人甲 say : count is 10
路人甲 say : count is 11
路人甲 say : count is 12
路人甲 say : count is 13
路人甲 say : count is 14
路人甲 say : count is 15
路人甲 say : count is 16
路人甲 say : count is 17
路人甲 say : count is 18
路人甲 say : count is 19
路人乙 say : count is 20

經過日誌能夠看出,基本是線程甲在執行,這是由於sleep時,機鎖一直在線程甲上,因此線程乙只能一直等待直到線程甲釋放鎖。對象

wait

1.wait()是Object類的一個方法。當調用wait()方法時,該線程會進入和該對象相關的等待池中,並釋放它所擁有的機鎖。資源

2.執行wait()後,必須使用notify()方法或notifyAll()方法或設置等待時間(wait(long time))喚醒在等待線程池中的線程。

3.wait()必須放在synchronized block中,不然會在運行時報「java.lang.IllegalMonitorStateException」異常

wait相關代碼

public class ThreadTest2 {

    public static void main(String[] args) {
        System.out.println("begin our test");
        ThreadSleep sleep = new ThreadSleep();
        try {
            Thread thread1 = new Thread(sleep, "路人甲");
            Thread thread2 = new Thread(sleep, "路人乙");
            thread1.start();
            thread2.start();
        } catch (Exception e) {
            e.printStackTrace();
        }
        System.out.println("test is over");
    }
}

class ThreadSleep implements Runnable {

    int count = 0;

    @Override
    public void run() {
        System.out.println(Thread.currentThread().getName() + " say : hello sleep !!");
        count();

    }

    public  void count() {
        while (count < 20) {
            synchronized (this) {
                System.out.println(Thread.currentThread().getName() + " say : count is " + count);
                try {
                    count++;
                    this.wait(100);
                } catch (Exception e) {
                    e.printStackTrace();
                }
            }
        }

    }
}

輸出日誌

begin our test
路人甲 say : hello sleep !!
路人甲 say : count is 0
test is over
路人乙 say : hello sleep !!
路人乙 say : count is 1
路人甲 say : count is 2
路人乙 say : count is 3
路人甲 say : count is 4
路人乙 say : count is 5
路人甲 say : count is 6
路人乙 say : count is 7
路人甲 say : count is 8
路人乙 say : count is 9
路人甲 say : count is 10
路人乙 say : count is 11
路人甲 say : count is 12
路人乙 say : count is 13
路人乙 say : count is 14
路人甲 say : count is 15
路人乙 say : count is 16
路人甲 say : count is 17
路人乙 say : count is 18
路人甲 say : count is 19

經過日誌能夠發如今wait的狀況下,機鎖會被釋放。

相關文章
相關標籤/搜索