目录
由于线程之间是抢占式执行的,我们不能确定线程的调度顺序,而有时候我们又希望多个线程之间可以有序地协调调度,于是就有了wait()和notify()方法。
wait()和notify()方法都是Object类中的方法,所以我们可以通过任意的对象来调用这些方法。
wait()方法表面上看起来只是让线程进入了等待的状态,实际上它要做三件事情:
(1) 释放当前的锁(所以调用wait()方法之前需要先加锁,即配合synchronized关键字使用);
(2) 使当前执行代码的线程进行等待;
(3) 满足一定条件时被唤醒(其他线程中调用了该对象的notify()方法),尝试重新获取锁。
注意:调用wait()方法的对象必须和synchronized的锁对象是同一个对象。
(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()方法是用来唤醒调用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();
- }
- }
代码运行结果:
相同点:都可以让线程放弃执行一段时间。
不同点:
(1) wait()是用于线程间通信的,sleep()是让线程阻塞一段时间;
(2) wait()需要搭配synchronized使用,sleep()不需要;
(3) wait()是Object类的成员方法,sleep()是Thread类的静态方法。