java
public class RunBlockQueue<T> {
private Integer maxSize;
private Queue<T> queue;
public RunBlockQueue(Integer maxSize) {
this.maxSize = maxSize;
this.queue = new ArrayDeque<>();
}
//生产者添加消息
public synchronized void add(T t) throws Exception{
//这里是while循环,防止线程被唤醒后继续添加
while (queue.size() >= maxSize) {
System.out.println(Thread.currentThread().getName() + "队列已满,进入休眠,释放锁");
wait();
}
//生产者生产消息
queue.add(t);
//通知消费者进行消费
this.notifyAll();
}
//消费者消费消息
public synchronized T get() throws Exception{
while (queue.size() == 0){
//当前线程休眠 并释放锁
this.wait();
}
//消费
T poll = queue.poll();
//消费了消息,通知生产者去生产
this.notifyAll();
return poll;
}
public static void main(String[] args) throws Exception {
RunBlockQueue<String> queue = new RunBlockQueue<>(10);
for (int i = 0; i < 10; i++) {
new Thread(() -> {
while (true){
try {
String data = UUID.randomUUID().toString();
queue.add(data);
System.out.println(Thread.currentThread().getName() + " 生产了数据 ===> " + data);
} catch (Exception e) {
e.printStackTrace();
}
}
}).start();
}
new Thread(() -> {
while (true){
String data = null;
try {
data = queue.get();
} catch (Exception e) {
e.printStackTrace();
}
System.out.println(Thread.currentThread().getName() + " 消费了数据 ===> " + data);
}
}).start();
}
}
消费/生产者模型
1. 当所有生产者达到生产阈值时,必须保证所有生产者都休眠,不会再去竞争锁,
2. 当所有消费者达到消费阈值时,必须保证所有消费者都休眠,不会再去竞争锁,让生产者去获取到锁去生产消息。
3. 当生产者没有达到生产阈值时,不需要休眠,依然可以继续竞争锁。
4. 当消费者没有达到消费阈值时,不需要休眠,依然可以继续竞争锁。
5. 生产/消费者 的方法同时只能执行一个方法
生产者每生产完消息后,会notifyAll唤醒或有线程(包括消费者,如果消费者能竞争得到锁)
消费者每消费完消息后,会notifyAll唤醒或有线程(包括生产者,如果生产者能竞争得到锁)
当消费者每消费完一个消息,都会执行notify方法,这样可以保证唤醒所有生产/消费线程
不管是生产/消费谁拿到锁,都会判断是否达到阈值,如果达到。
确保生产/消费不会同时休眠就是要保证判断条件不会同时满足休眠,例如生产者是队列满时才休眠,消费者是队列空时才休眠,这两个条件显示不会同时满足,所以不会造成 生产/消费 同时休眠。