前言
今天又来讲讲我们之前只讲了一点的Javaee基础知识,今天要理解的是wait与notify,关于多线程这两个方法我们也是要理解的,那么我们今天就开始来深入理解一下。
wiat与notify的简单认识
wait和notify是Object类的方法,也就是任何对象都会存在这两个方法。那么这两个方法存在的意义是什么呢?
首先我们要知道操作系统对线程的执行时随机的,即抢占式的方式,我们无法预知哪个线程先执行哪个线程后执行,那么这时使用wait和notify,就可以实现控制线程的执行顺序,后执行的程序就可以先调用wait方法等待,让其他线程先执行。
wait的作用:使当前执行代码的线程进行等待,停止继续运行(把线程放入等待队列中),且释放锁,释放资源,让其他线程可以开始获取锁。需要注意的是wait是要在synchronized中使用的,否则就会抛出异常
notify:发出通知唤醒对象头为当前对象的,处于等待状态过程中的线程。
wait()方法详解
首先再次讲述一下wait()方法的功能:
- 停止当前执行代码的线程进入等待状态,将其放入等待队列中。
- 释放当前的锁,释放cpu资源。
- 当满足一定条件时,会重新获取这个锁。
那么唤醒有哪些条件呢?
- 首先就是其它线程notify
- 等待时间已经到了,wait方法是可以指定时间的wiat(long timeout)。
- 其他线程调⽤该等待线程的 interrupted ⽅法, 导致 wait 抛出 InterruptedException 异常.
那么下面我们演示一下基本的wait()方法的使用:
public class Main {
public static void main(String[] args) throws InterruptedException {
Object object = new Object();
synchronized (object) {
System.out.println("等待中");
object.wait();
System.out.println("等待结束");
}
}
}
如上代码我们这么写就是死等,如果没有其它线程来唤醒,或者调用其interrupted()方法,他就会一直等待下去。
notify()方法详解
notify的功能:
唤醒其它处于等待状态的线程(属于该对象头的线程)
注意事项:
notify也需要在synchronized中使用。
首先我们得如果要唤醒得对象有多个,那么这时唤醒的线程也是随机的(没有“先来后到的说法”)
其次我们的唤醒并不是执行完notify后就立马生效,而是需要等待notify处于的同步代码块执行完。即走出synchronized的大括号。
用代码更加直观的展示两个方法的使用:
我们创建了两个类,一个WaitTask,NotifyTask,并且重写了他们的run方法,具体就是通过他们的打印顺序给大家展示一下他们的执行顺序
public class Main {
public static void main(String[] args) throws InterruptedException {
Object locker = new Object();
Thread t1 = new Thread(new WaitTask(locker));
Thread t2 = new Thread(new NotifyTask(locker));
t1.start();
Thread.sleep(1000);
t2.start();
}
static class WaitTask implements Runnable {
private Object locker;
public WaitTask(Object locker) {
this.locker = locker;
}
@Override
public void run() {
synchronized (locker) {
while (true) {
try {
System.out.println("wait 开始");
locker.wait();
System.out.println("wait 结束");
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
}
}
static class NotifyTask implements Runnable {
private Object locker;
public NotifyTask(Object locker) {
this.locker = locker;
}
@Override
public void run() {
synchronized (locker) {
System.out.println("notify 开始");
locker.notify();
System.out.println("notify 结束");
}
}
}
}
notifyAll方法
作用与notify相似,但他会将等待的线程全部唤醒,但是唤醒的顺序还是随机的。
面试常考:
|
特性 |
wait() |
sleep() |
|
类所属 |
Object |
Thread |
|
调用位置 |
必须在同步方法或同步代码块中调用 |
可以在任何地方调用 |
|
释放锁 |
会释放锁 |
不释放锁 |
|
唤醒机制 |
需要 notify() 或 notifyAll() 唤醒 |
自动恢复执行,不需要唤醒机制 |
|
用途 |
线程通信与协作(如生产者-消费者模式) |
控制线程的暂停时间 |
总的来说,wait() 主要用于线程间的协作和通信,sleep() 主要用于线程的暂停控制,二者的功能和使用场景有很大的不同。

1106





