Java多線程學習(二)wait、notify、notifyAll詳解

一、整體圖表

在這裏插入圖片描述

二、補充知識

下圖取之Java線程狀態
在這裏插入圖片描述
如上圖所示:

  1. 總共分爲六個狀態(運行態和就緒態歸爲運行態)

三、具體方法

3.1 wait方法

3.1.1定義

讓線程進入等待並且釋放鎖。

3.1.2注意

  1. 當前線程必須持有該對象的鎖
  2. wait必須被喚醒後或者設置時間進入隊列才能繼續執行接下來的操作

3.1.3使用方式

  public static Object object = new Object();

    public static void main(String[] args) throws InterruptedException {
        Thread thread1 = new Thread(new Thread1());
        thread3.start();

    }

    static class Thread1 implements Runnable {
        @Override
        public void run() {
            //比如在同步代碼塊或者方法裏且得到該對象的鎖
            synchronized (object) {
                System.out.println(Thread.currentThread().getName() + " is running.");
                try {
                    //對象進入等待
                    object.wait();
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
                System.out.println(Thread.currentThread().getName() + " get the lock.");
            }
        }
    }

3.2 notify方法

3.2.1定義

喚醒任意一個等待的線程。

3.2.2注意

  1. 當前線程必須持有該對象的鎖
  2. notify後會喚醒一個正在等待的線程
  3. 但是當前線程不會馬上放棄鎖的持有權,而是在同步代碼執行完畢後纔會釋放鎖

3.2.3 使用方式

//步驟
//1.先讓線程0執行然後進行等待
//2.再讓線程1執行然後通過 notify 喚醒0線程(因爲等待隊列只有0線程)
//3.線程1執行結束後會執行線程0
  public static Object object = new Object();
  
    public static void main(String[] args) throws InterruptedException {
        Thread thread1 = new Thread(new Thread1());
        Thread thread2 = new Thread(new Thread2());
        thread1.start();
        Thread.sleep(1000);
        thread2.start();

    }

    static class Thread1 implements Runnable {
        @Override
        public void run() {
            synchronized (object) {
                System.out.println(Thread.currentThread().getName() + "  running.");
                try {
                    object.wait();
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
                System.out.println(Thread.currentThread().getName() + " get the lock.");
            }
        }
    }


    static class Thread2 implements Runnable {
        @Override
        public void run() {
            synchronized (object) {
                System.out.println(Thread.currentThread().getName() + " is running.");
                object.notify();
                System.out.println(Thread.currentThread().getName() + " invoke notify()");
                System.out.println(Thread.currentThread().getName() + " release the lock.");
            }
        }
    }

//結果:
Thread-0  running.
Thread-1 is running.
Thread-1 invoke notify()
Thread-1 release the lock.
Thread-0 get the lock.

3.3 notifyAll

3.3.1定義

喚醒所有在等待的鎖。

3.3.2注意

  1. 當前線程必須持有該對象的鎖
  2. notify後會喚醒所有在等待的鎖
  3. 但是當前線程不會馬上放棄鎖的持有權,而是在同步代碼執行完畢後纔會釋放鎖

3.3.3 使用方式

步驟

  1. 先讓線程0以及線程1執行然後進行等待
  2. 再讓線程2執行然後通過 notifyAll 喚醒所有線程並進入終止狀態(TERMINATED
  3. 線程0,1從等待狀態(WAITING)進入阻塞(BLOCKED)狀態
  4. 線程1獲得鎖進入運行狀態(RUNNABLE
  5. 之後線程1進入終止狀態(TERMINATED),線程0進入運行狀態(RUNNABLE),之後終止(TERMINATED

執行順序:

  public static Object object = new Object();

    public static void main(String[] args) throws InterruptedException {
        Thread thread1 = new Thread(new Thread1());
        Thread thread2 = new Thread(new Thread2());
        Thread thread3 = new Thread(new Thread3());
        thread1.start();
        thread2.start();
        Thread.sleep(1000);
        thread3.start();

    }

    static class Thread1 implements Runnable {
        @Override
        public void run() {
            synchronized (object) {
                System.out.println(Thread.currentThread().getName() + "  running.");
                try {
                    object.wait();
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
                System.out.println(Thread.currentThread().getName() + " get the lock.");
            }
        }
    }
    static class Thread2 implements Runnable {
        @Override
        public void run() {
            synchronized (object) {
                System.out.println(Thread.currentThread().getName() + "  running.");
                try {
                    object.wait();
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
                System.out.println(Thread.currentThread().getName() + " get the lock.");
            }
        }
    }

    static class Thread3 implements Runnable {
        @Override
        public void run() {
            synchronized (object) {
                System.out.println(Thread.currentThread().getName() + " is running.");
                object.notifyAll();
                System.out.println(Thread.currentThread().getName() + " invoke notifyAll()");
                System.out.println(Thread.currentThread().getName() + " release the lock.");
            }
        }
    }

結果:
Thread-0  running.
Thread-1  running.
Thread-2 is running.
Thread-2 invoke notifyAll()
Thread-2 release the lock.
Thread-1 get the lock.
Thread-0 get the lock.
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章