目录
wait和notify
是多线程中一个比较重要的机制,协调多个线程的执行顺序的
本身多个线程的执行顺序是随机的(抢占式 系统随机调度)
我们希望通过一定手段控制线程执行顺序
wait等待,让指定线程进入阻塞状态
notify通知,唤醒对应的阻塞状态的线程
wait和notify需要借助同一个对象,并且都需要搭配synchronized使用
wait等待——进入阻塞
Object object=new Object();
System.out.println("wait之前");
object.wait(3000);
System.out.println("wait之后");
报错IllegalMonitorStateException非法的监视器状态异常
此处的监视器指synchronized(也叫监视器锁)
原因:
wait在执行的时候,要做三件事
①释放当前锁
②让线程进入阻塞
③当线程被唤醒的时候,重新获取到锁
(①也就意味着,我们需要提前加上锁)
正确使用方式:
Object object1 = new Object();
synchronized (object) {
System.out.println("wait 之前");
// 把 wait 要放到 synchronized 里面来调用. 保证确实是拿到锁了的.
object1.wait();
System.out.println("wait 之后");
}
注意:
wait只能由持有相应对象监视器锁的线程调用 也就是说加锁的对象(object1)要与调用wait的对象式=是同一个
wait会持续阻塞等待下去,直到其他线程调用notify唤醒
wait还有一个有参版本,指定了最多等待时间
使用wait notify也可以避免”线程饿死“
使用wait后(wait内部本身会释放锁,并且进入阻塞),1号就不会参与后续的锁竞争了,把锁释放出来让别人获取
wait是等的状态,是阻塞的,啥都不做,不会占据cpu
notify唤醒线程
notify一次唤醒一个线程
notiftAll一次唤醒全部线程(多个线程调用wait)(
public static void main(String args[]) throws InterruptedException {
Object object=new Object();
Thread t1=new Thread(()->{
synchronized (object){
System.out.println("t1获取锁");
try {
object.wait();
} catch (InterruptedException e) {
throw new RuntimeException(e);
}
System.out.println("t1再次获取锁");
}
});
Thread t2=new Thread(()->{
synchronized (object){
System.out.println("t2获取锁");
object.notify();
System.out.println("t2仍在运行");
}
});
t1.start();
t2.start();
}
①调用 wait 方法后,释放持有的对象锁,线程状态有 Running 变为 Waiting,并将当前线程放置到对象的 等待队列;
②调用notify 或者 notifyAll 方法后,等待线程依旧不会从 wait 返回,需要调用 noitfy 的线程释放锁之后,等待线程才有机会从 wait 返回;
③notify 方法:将等待队列的一个等待线程从等待队列种移到同步队列中 ,
④notifyAll 方法:将等待队列种所有的线程全部移到同步队列,被移动的线程状态由 Waiting 变为 Blocked。
————————————————
原文链接:https://blog.csdn.net/qq_40662405/article/details/120484313