线程等待机制——wait/notify(notifyAll)
Posted 无赖H4
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了线程等待机制——wait/notify(notifyAll)相关的知识,希望对你有一定的参考价值。
wait、notify、notifyAll属于Object类下的三个普通方法
(java中所有对象都具备这三个方法)
基本使用规则:对象.wait(),使得线程进入“等待”状态,直到有其他线程,在同一个对象上调用notify/notifyAll()方法
语法
关于wait和notify的使用规则,必须先对等待的对象,通过synchronized加锁
Object o = new Object();//等待唤醒的对象
synchronized (o){
o.wait();//如果不这么操作,会收到异常
}
synchronized(o){
o.notify();
}
唤醒的线程如何知道有哪些对象在o这个对象上?
等待集(wait set):保存等在对象上的所有线程
wait:把当前线程加入到等待集中
notify:从wait set删除掉一个线程
由于多个线程修改共享数据,所以需要synchronized保护
wait
wait()的作用就是让当前线程进入等待状态,同时也会让当前线程释放它所持有的锁,直到其他线程调用notify()或notifyAll()方法,被唤醒进入就绪状态;
wait()
wait() / wait(long timeout) / wait(long timeout, int nanos)
time out : 超时
wait什么时候会醒过来:
1、会被别的线程唤醒
2、会在到达超时时间时
3、会在被别的进程打断(interrupt)时->收到一个InterruptException异常
4、由于系统原因,可能出现假唤醒——毫无征兆的醒来
加锁
在o.wait()时,需要进行加锁,当wait成功,会释放锁,但不是释放所有锁,只释放o这把锁.
当wait被唤醒时,会重新对o进行加锁操作
notify
- notify()会唤醒等待在对象上的一个线程,但是它是随机唤醒
- notifyAll()会唤醒等待在对象上的所有线程
- notify()会有状态保留吗?
例如:当线程A调用了o.notify();线程B在调用o.wait();是等待呢,还是被唤醒?
A会等待,没有状态保留
使用场景
A线程是等待线程,B线程是唤醒线程
A线程在等待某个条件发生的时候(例如:a==1),当条件没有满足的时候,wait
B线程,会在某些情况下,使得条件成立(a = 1),当条件成立的时候,B有责任唤醒A
A:
if(a != 1){
sync(o){
o.wait()
}
}
B:
a = 1;
o.notify();
这里,我们可以将if换为while保证wait又可能唤醒
例子:
import java.util.Scanner;
public class Demo1 {
private static final Object o = new Object();
static class MyThread extends Thread {
@Override
public void run() {
try {
System.out.println("我即将进入等待状态");
synchronized (o) {
o.wait();
}
System.out.println("我被别的线程唤醒了");
} catch (InterruptedException exc) {
exc.printStackTrace();
}
}
}
public static void main(String[] args) throws InterruptedException {
MyThread thread = new MyThread();
thread.start();
Scanner s = new Scanner(System.in);
System.out.println("等待我们的输入,我们不输入,不继续");
s.nextLine();
System.out.println("有输入,进行线程的唤醒操作");
synchronized (o) {
o.notify();
}
}
}
wait和sleep对比
Thread.sleep(ms)/TimeUnit.*.sleep()
和
o.wait();
的区别:
相同现象:
1、造成线程的阻塞(停止运行),状态是TIME_WAITING
2、貌似都是等待xx时间后继续运行
差异点:
1、wait等待的时间<=timeout,sleep== timeout
2、语义上不同 (核心)
3、锁/wait有锁的释放(不是所有锁);sleep和锁无关
4、写法不同
以上是关于线程等待机制——wait/notify(notifyAll)的主要内容,如果未能解决你的问题,请参考以下文章
sleep,yield,wait,notify,notifyAll