Java多线程学习(二)wait、notify、notifyAll详解

一、整体图表

Java多线程学习(二)wait、notify、notifyAll详解

二、具体方法

2.1 wait方法

2.1.1定义

让线程进入等待并且释放锁。

2.1.2注意

  1. 当前线程必须持有该对象的锁
  2. wait必须被唤醒后或者设置时间进入队列才能继续执行接下来的操作

2.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.");
            }
        }
    }

2.2 notify方法

2.2.1定义

唤醒任意一个等待的锁。

2.2.2注意

  1. 当前线程必须持有该对象的锁
  2. notify后会唤醒一个正在等待的线程
  3. 但是当前线程不会马上放弃锁的持有权,而是在同步代码执行完毕后才会释放锁

2.2.2 使用方式

//步骤
//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.

2.3 notifyAll

2.3.1定义

唤醒所有在等待的锁。

2.3.2注意

  1. 当前线程必须持有该对象的锁
  2. notify后会唤醒所有在等待的锁
  3. 但是当前线程不会马上放弃锁的持有权,而是在同步代码执行完毕后才会释放锁

2.3.3 使用方式

//步骤
//1.先让线程0以及线程1执行然后进行等待
//2.再让线程2执行然后通过 notifyAll 唤醒所有线程
//3.线程2执行结束后会执行线程0和1

  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.