java併發編程學習之線程的生命週期-wait,notify,notifyall(六)

sleep和wait

  1. sleep是Thread類的方法,wait是Object的方法。
  2. sleep能夠處處使用,wait必須是在同步方法或者代碼塊裏使用,否則會有java.lang.IllegalMonitorStateException異常。
  3. sleep不釋放持有的鎖,wait釋放鎖。wait在調用方法前,必須持有鎖,調用notify,notifyall喚醒,也要持有鎖。
  4. sleep休眠必定時間後,進入就緒狀態。wait由notify和notifyall喚醒。這兩個都能被interrupt方法中斷當前狀態。

join和yield

這兩個和sleep同樣,不釋放持有的鎖。java

示例

public class WaitDemo {
    private String tv = "廣告";

    static class Tv extends Thread {
        WaitDemo waitDemo;

        public Tv(WaitDemo waitDemo) {
            this.waitDemo = waitDemo;
        }

        @Override
        public void run() {
            waitDemo.waitTv();
        }
    }

    public synchronized void waitTv() {
        while (tv.equals("廣告")) {
            try {
                wait();
                if (tv.equals("廣告")) {
                    System.out.println(Thread.currentThread().getName() + "-" + "騙人,仍是廣告");
                }
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }
        System.out.println(Thread.currentThread().getName() + "-" +"愉快的追劇");
    }

    public synchronized void sendTrueMsg() {
        tv = "正劇";
        notifyAll();
    }

    public synchronized void sendFalseMsg() {
        notifyAll();
    }

    public static void main(String[] args) throws InterruptedException {
        WaitDemo waitDemo = new WaitDemo();
        Tv tv1 = new Tv(waitDemo);
        Tv tv2 = new Tv(waitDemo);
        tv1.start();
        tv2.start();
        Thread.sleep(100);
        waitDemo.sendFalseMsg();
        Thread.sleep(100);
        waitDemo.sendTrueMsg();
    }
}

運行的結果以下:
clipboard.png
例子:大部分人喜歡看連續劇,可是不看廣告(沒錢買VIP),因而就讓別人提醒她廣告結束了沒有,若是結束了,就提醒她。
用法:多線程

wait方

  1. 獲取鎖
  2. while判斷條件,不知足繼續wait
  3. 知足執行其餘業務

notify方

  1. 獲取鎖
  2. 改變條件
  3. 通知

爲何是while而不是if

while會一直循環,直到條件知足。若是是if,只會判斷一次,若是不知足條件,會一直等待ide

爲何是notifyAll而不是notify

能夠把上面的例子,改爲notify,那麼進程永遠不會結束,由於在多線程狀況下,notify只能喚醒隨機的一個休眠線程,其餘已休眠的線程不能喚醒,形成信號不能傳達而丟失,而notifyAll能夠喚醒全部的。this

相關文章
相關標籤/搜索