介绍
synchronized中,使用wait进行等待阻塞,使用 notify 或 notifyAll 进行唤醒,将线程从条件队列中挪动到等待队列(这里是按照管程模型来讲的,没看过源码,注释中也没提,暂时按模型来好了),notify是任意唤醒一个,notifyAll是唤醒全部。注意,notify是任意唤醒一个,具体的唤醒哪一个,也就是唤醒方式是随机唤醒一个,还是按照加入条件队列的顺序唤醒,或者是按照优先级唤醒,又或者是其他什么方式等等都由实现者也就是 JVM 决定,而不是随机唤醒一个。
实现生产者-消费者模式
下面的生产者与消费者线程中的循环只是做个演示,存在有bug,如果生产者线程生命周期中生产数量与消费者线程生命周期中消费数量不匹配则会有线程阻塞
商品
public class Resource {
//存储商品
private Queue<Object> goodsQueue = new LinkedList<>();
//商品最大数量
private final int MAX_GOODS_NUM = 8;
//生产
public synchronized void produce(Object goods) throws InterruptedException {
//当产品数量等于最大数量,停止生产,等待消费
while(goodsQueue.size() == MAX_GOODS_NUM){
wait();
}
//如果当前产品数量等于0,则有可能消费者线程在条件队列阻塞中
if(goodsQueue.size() == 0){
goodsQueue.add(goods);
notifyAll();
}else{
goodsQueue.add(goods);
}
}
public synchronized Object consume() throws InterruptedException {
while(goodsQueue.size() == 0){
wait();
}
if(goodsQueue.size() == MAX_GOODS_NUM){
Object res = goodsQueue.poll();
notifyAll();
return res;
}else {
return goodsQueue.poll();
}
}
}
消费者
public class Consumer implements Runnable{
private Resource resource;
public Consumer(Resource _resource){
this.resource = _resource;
}
@Override
public void run() {
try {
for (int i = 0; i < 10; i++) {
resource.consume();
System.out.println(i+"消费者消费了商品...");
}
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
生产者
public class Producer implements Runnable{
private Resource resource;
public Producer(Resource _resource){
this.resource = _resource;
}
@Override
public void run() {
try {
for (int i = 0; i < 10; i++) {
resource.produce(new Object());
System.out.println(i+"生产者生产了商品...");
}
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}