wait、notify、notifyAll
1、在多线程环境下,有时候一个线程的执行,依赖于另外一个线程的某种状态的改变,这个时候,我们就可以使用wait与notify或者notifyAll
2、wait跟sleep的区别:wait会释放持有的锁,而sleep不会,sleep只是让线程在指定的时间内,不去抢占cpu的资源
3、注意点:wait notify必须放在同步代码块中, 且必须拥有当前对象的锁,即不能取得A对象的锁,而调用B对象的wait 哪个对象wait,就得调哪个对象的notify
4、notify跟notifyAll的区别:nofity随机唤醒一个等待的线程 notifyAll唤醒所有在该对象上等待的线程
public class Demo {
private static volatile boolean flag = false;
public static void main(String[] args) throws InterruptedException {
// 线程1,while循环中的参数一直为false,需要等线程2先执行完
new Thread(()->{
while (!flag) {
try {
Thread.sleep(1000L);
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println("flag is false");
}
System.out.println("flag is true");
}).start();
// 休眠
Thread.sleep(1000L);
// 线程2,将flag设置为true,线程1需要等待线程2执行完
new Thread(()->{
flag = true;
}).start();
}
}
# 控制台结果:
flag is false
flag is true
public class Demo1 {
private static volatile boolean flag = false;
public static void main(String[] args) throws InterruptedException {
Object obj = new Object();
new Thread(()->{
while (!flag) { // 为true
synchronized (obj) { // 获取锁
try {
System.out.println("flag is false"); // (1)
obj.wait(); // 挂起线程
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
System.out.println("flag is true"); // (3)
}).start();
new Thread(()->{
while (!flag) {
synchronized (obj) {
try {
System.out.println("flag is false"); // (2)
obj.wait();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
System.out.println("flag is true"); // (4)
}).start();
// 休眠1秒
Thread.sleep(1000L);
new Thread(()->{
flag = true;
synchronized (obj) {
obj.notifyAll(); // 唤醒所有等待的线程
}
}).start();
}
}
# 控制台
flag is false
flag is false
flag is true
flag is true
等待通知经典模型之生产者消费者
# 中间商
public class Medium {
private int num = 0;
// 库存量
private static final int TOTAL = 20;
/**
* 接收生产数据
*/
public synchronized void put() {
//判断当前的库存,是否已经是最大的库存容量
if (num < TOTAL) {
//如果不是,生产完成之后,通知消费者进行消费
System.out.println("新增库存-------->当前库存" + ++num);
try {
Thread.sleep(500L);
} catch (InterruptedException e) {
e.printStackTrace();
}
notifyAll(); // 唤醒所有等待线程
} else {
//如果是,则通知生产者进行等待
try {
System.out.println("新增库存---------> 库存已满"+num);
wait();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
/**
* 获取消费数据
*/
public synchronized void take() {
//判断当前库存是否不足
if (num > 0) {
//如果充足,在消费完成之后通知生产者进行生产
System.out.println("消费库存-----------> 当前库存容量" + --num);
try {
Thread.sleep(1000L);
} catch (InterruptedException e) {
e.printStackTrace();
}
notifyAll();
} else {
//如果不足,通知消费者暂停消费
System.out.println("消费库存-----------> 库存不足"+num);
try {
wait();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
}
# 生产者
public class Producer implements Runnable {
private Medium medium;
public Producer(Medium medium) {
this.medium = medium;
}
@Override
public void run() {
while (true) {
medium.put();
}
}
}
# 消费者
public class Consumer implements Runnable{
private Medium medium;
public Consumer(Medium medium) {
this.medium = medium;
}
@Override
public void run() {
while (true) {
medium.take();
}
}
}
# 测试类
public class Main {
public static void main(String[] args) {
Medium medium = new Medium();
// new 3个消费者
new Thread(new Consumer(medium)).start();
new Thread(new Consumer(medium)).start();
new Thread(new Consumer(medium)).start();
// new 5个生产者
new Thread(new Producer(medium)).start();
new Thread(new Producer(medium)).start();
new Thread(new Producer(medium)).start();
new Thread(new Producer(medium)).start();
new Thread(new Producer(medium)).start();
}
}