1、wait / notify 原理
- Owner线程发现条件不满足,调用wait方法,即可进入WaitSet变为WAITING状态
- BLOCKED和WAITING的线程都处于阻塞状态,不占用CPU时间片
- BLOCKED线程会在Owner线程释放锁的时候被唤醒
- WAITING线程会在Owner线程调用notify或notifyAll时唤醒,但唤醒后并不意味着立刻获得锁,仍需进入EntryList重新竞争
2、API介绍
-
obj.wait()让进入object监视器的线程到waitSet等待
-
obj.notify()在object上正在waitSet’等待的线程中挑一个唤醒
-
obj.notifyAll()让object上正在waitSet等待的线程全部唤醒
他们都是线程之间协作的手段,都属于Object的方法。必须获得对象的锁,才能调用这几个方法
当没有锁时,抛出异常
public class WaitAndNotify {
static final Object Lock = new Object();
public static void main(String[] args) {
try {
Lock.wait();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
正确姿势
public class WaitAndNotify {
static final Object Lock = new Object();
public static void main(String[] args) {
synchronized (Lock) {
try {
Lock.wait();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
}
3、练习
package com.sharing_model.wait_notify;
/**
* wait notify 正确使用
*/
public class WaitAndNotifyTrueUse {
static final Object room = new Object();
static boolean hasCigarette = false;
public static void main(String[] args) throws InterruptedException {
new Thread(() -> {
System.out.println("有烟没?" + hasCigarette);
synchronized (room) {
if (!hasCigarette) {
System.out.println(" 没烟,小南先休息一会!");
try {
room.wait();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
System.out.println("有烟没?" + hasCigarette);
if (hasCigarette) {
System.out.println("小南开始干活了");
}
}
}, "小南").start();
for (int i = 0 ; i < 5 ; i++) {
new Thread(() -> {
synchronized (room) {
System.out.println("其它人开始干活了");
}
},"其它人").start();
}
Thread.sleep(1);
new Thread(() -> {
synchronized (room) {
System.out.println("有烟了");
hasCigarette = true;
room.notify();
}
}).start();
}
}
总结:
synchronized(lock) {
while(条件不成立) {
lock.wait();
}
//干活
}
//另一个线程
synchronized(lock) {
lock.notifyAll();
}