Java中的wait和notify方法

目录

一、前言

二、wait()方法

1、wait()方法要做的事

2、结束等待的方式

三、notify()方法

四、wait()和sleep()的对比


一、前言

        由于线程之间是抢占式执行的,我们不能确定线程的调度顺序,而有时候我们又希望多个线程之间可以有序地协调调度,于是就有了wait()notify()方法。

       wait()notify()方法都是Object类中的方法,所以我们可以通过任意的对象来调用这些方法。

二、wait()方法

1、wait()方法要做的事

wait()方法表面上看起来只是让线程进入了等待的状态,实际上它要做三件事情:

(1) 释放当前的锁(所以调用wait()方法之前需要先加锁,即配合synchronized关键字使用);

(2) 使当前执行代码的线程进行等待;

(3) 满足一定条件时被唤醒(其他线程中调用了该对象的notify()方法),尝试重新获取锁。

注意:调用wait()方法的对象必须和synchronized的锁对象是同一个对象。

2、结束等待的方式

(1) 其他线程中调用了该对象的notify()方法;

(2) 如果调用的是带参数的wait()方法(可以传入参数来指定等待的时间),等待时间结束即可;

(3) 其他线程中调用该等待线程的interrupted()方法,提前唤醒该等待线程,同时也会抛出InterruptedException异常。

public class Test3 {
    public static void main(String[] args) throws InterruptedException {
        Thread t1 = new Thread(() -> {
            synchronized (Test3.class) {
                try {
                    //t1线程进入wait状态
                    //锁对象和调用wait方法的对象必须是同一个
                    Test3.class.wait();
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
            }
            System.out.println("t1线程结束");
        });
        t1.start();
        //t1线程启动后休眠1秒
        Thread.sleep(1000);

        Thread t2 = new Thread(() -> {
            t1.isInterrupted();
            System.out.println("t2线程中设置标志位");
            t1.interrupt();
        });
        t2.start();
    }
}

 

注意:调用wait()方法和notify()方法的对象必须是同一个,否则无法唤醒线程。

三、notify()方法

        notify()方法是用来唤醒调用wait()方法后进入等待的线程,但是调用两个方法的对象必须是同一个对象,如果在线程1中通过A对象调用wait(),而在线程2中通过B对象调用notify(),则无法唤醒A对象所在的线程。

注意:

(1) 如果多个线程中都通过对象A都调用了wait(),那么另外一个线程中通过对象A调用notify(),只会随机唤醒其中一个线程;要想唤醒所有线程,需要调用notifyAll()方法。

(2) 如果线程2先调用notify(),线程1再调用wait(),则线程1会一直等待,无法被唤醒。

代码示例:在t2线程中调用notify()唤醒调用了wait()t1线程

public class Test4 {
    public static void main(String[] args) throws InterruptedException {
        Object object = new Object();
        Thread t1 = new Thread(() -> {
            synchronized (object){
                System.out.println("调用wait之前");

                try {
                    object.wait();
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }

                System.out.println("调用wait之后");
            }
        });
        t1.start();
        //t1线程启动后休眠100毫秒,保证先执行t1再执行t2
        Thread.sleep(100);

        Thread t2 = new Thread(() -> {
            synchronized (object){
                System.out.println("调用notify之前");

                object.notify();

                System.out.println("调用notify之后");
            }
        });
        t2.start();
    }
}

代码运行结果:

 

四、wait()和sleep()的对比

相同点:都可以让线程放弃执行一段时间。

不同点:

(1)wait()是用于线程间通信的,sleep()是让线程阻塞一段时间;

(2)wait()需要搭配synchronized使用,sleep()不需要;

(3)wait()Object类的成员方法,sleep()Thread类的静态方法。


版权声明:本文为m0_67683346原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接和本声明。