public class WaitSetDemo {
private static final Object LOCK = new Object();
public static void main(String[] args) {
IntStream.rangeClosed(1,10).forEach(i->
new Thread(){
@Override
public void run() {
synchronized (LOCK){
try {
System.out.println(Thread.currentThread().getName()+"马上睡觉");
LOCK.wait();
System.out.println(Thread.currentThread().getName()+"要离开休息室");
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
}.start()
);
IntStream.rangeClosed(1,10).forEach(i->{
synchronized (LOCK){
LOCK.notify();
}
});
}
}
//执行结果
Thread-0马上睡觉
Thread-6马上睡觉
Thread-7马上睡觉
Thread-8马上睡觉
Thread-9马上睡觉
Thread-5马上睡觉
Thread-4马上睡觉
Thread-3马上睡觉
Thread-1马上睡觉
Thread-2马上睡觉
Thread-0要离开休息室
Thread-2要离开休息室
Thread-1要离开休息室
Thread-3要离开休息室
Thread-4要离开休息室
Thread-5要离开休息室
Thread-9要离开休息室
Thread-8要离开休息室
Thread-7要离开休息室
Thread-6要离开休息室
总结:
1、HotSpot 版本虚拟机线程wait后唤醒顺序不是FIFO;
2、线程被唤醒后必须重新去获取锁,程序计数器会记录线程的进入wait时的位置,被唤醒后会从wait位置继续往下执行;这也同时证明了,程序计数器对线程是私有的
3、Java中每个对象都会有一个wait set,用来存放调用了该对象的wait方法之后进入阻塞状态的线程;
//wait方法是Object类中的方法,所以每个对象都可以调用
public class Object {
public final native void wait(long timeout) throws InterruptedException;
}
4、线程被notify唤醒后,不会立即执行,需要抢锁(这也是synchronized为什么是非公平锁的原因)