一、线程间等待与唤醒机制
wait()
和notify()
是Object类的方法,用于线程的等待与唤醒,必须搭配synchronized 锁来使用。
多线程并发的场景下,有时需要某些线程先执行,这些线程执行结束后其他线程再继续执行。
比如:一个长跑比赛,裁判员要等跑步运动员冲线了才能宣判比赛结束,那裁判员线程就得等待所有的运动员线程运行结束后,再唤醒这个裁判线程。
二、等待方法wait()
wait 做的事情:
-
使当前执行代码的线程进行等待. (把线程放到等待队列中)
-
释放当前的锁
-
满足一定条件时被唤醒, 重新尝试获取这个锁.
wait 要搭配 synchronized 来使用. 脱离 synchronized 使用 wait 会直接抛出异常.
图片
wait 结束等待的条件:
-
其他线程调用该对象的 notify 方法.
-
wait 等待时间超时 (wait 方法提供一个带有 timeout 参数的版本, 来指定等待时间).
-
其他线程调用该等待线程的
interrupted
方法, 导致 wait 抛出InterruptedException
异常.
注意事项:
-
调用
wait()
方法的前提是首先要获取该对象的锁(synchronize对象锁) -
调用
wait()
方法会释放锁,本线程进入等待队列等待被唤醒,被唤醒后不是立即恢复执行,而是进入阻塞队列,竞争锁
等待方法:
1.痴汉方法,死等,线程进入阻塞态(WAITING
)直到有其他线程调用notify方法唤醒
图片
2.等待一段时间,若在该时间内线程被唤醒,则继续执行,若超过相应时间还没有其他线程唤醒此线程,此线程不再等待,恢复执行。
图片
调用wait方法之后:
图片
三、唤醒方法notify()
notify 方法是唤醒等待的线程.
-
方法
notify()
也要在同步方法或同步块中调用,该方法是用来通知那些可能等待该对象的对象锁的其它线程,对其发出通知notify,并使它们重新获取该对象的对象锁。 -
如果有多个线程等待,则有线程调度器随机挑选出一个呈
wait
状态的线程。(并没有 “先来后到”) -
在
notify()
方法后,当前线程不会马上释放该对象锁,要等到执行notify()
方法的线程将程序执行完,也就是退出同步代码块之后才会释放对象锁。
注意事项:
-
notify()
:随机唤醒一个处在等待状态的线程。 -
notifyAll()
:唤醒所有处在等待状态的线程。
无论是wait还是notify方法,都需要搭配synchronized锁来使用(等待和唤醒,也是需要对象)