所谓的生产者消费者模型,是通过一个容器来解决生产者和消费者的强耦合问题。通俗的讲,就是生产者在不断的生产,消费者也在不断的消费,可是消费者消费的产品是生产者生产的,这就必然存在一个中间容器,我们可以把这个容器想象成是一个货架,当货架空的时候,生产者要生产产品,此时消费者在等待生产者往货架上生产产品,而当货架满的时候,消费者可以从货架上拿走商品,生产者此时等待货架的空位,这样不断的循环。
具体实现代码如下,都是笔者手撸!!
class ProductAndConsumerDemo {
public static void main(String[] args) {
Buffer buffer = new Buffer();
Consumer consumer = new Consumer(buffer);
Product product = new Product(buffer);
consumer.start();
product.start();
}
}
class Product extends Thread {
private Buffer buffer;
public Product(Buffer buffer) {
this.buffer = buffer;
}
public void run() {
for (int i = 0; i < 10; i++) {
try {
buffer.add(i);
System.out.println("加入第"+i+"个线程");
Thread.sleep(1000);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
}
class Consumer extends Thread {
private Buffer buffer;
public Consumer(Buffer buffer) {
this.buffer = buffer;
}
public void run() {
for (int i = 0; i < 10; i++) {
int val = 0;
try {
val = buffer.pull();
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println(val);
}
}
}
class Buffer {
private Queue<Integer> queue = new LinkedList<>();
private int size = 5;
private Buffer buffer;
public synchronized void add(int val) throws InterruptedException {
while (queue.size() > size)//此处如果使用if,多线程环境下会造成虚假唤醒
wait();//阻塞生产者不让其继续生产
queue.add(val);
notify();通知消费者消费(notify()会唤醒正在等待的线程,此处指消费者线程)
}
public synchronized int pull() throws InterruptedException {
while (queue.size() == 0)
wait();
int val = queue.poll();
notify();
return val;
}
}
代码已经经过调试,大家可随意copy到本地IDE去体验生产者/消费者的概念。
Lock版的生产者消费者模型
class BoundedBuffer {
final Lock lock = new ReentrantLock();
final Condition notFull = lock.newCondition();
final Condition notEmpty = lock.newCondition();
final Object[] items = new Object[100];
int putptr, takeptr, count;
public void put(Object x) throws InterruptedException {
lock.lock(); try {
while (count == items.length)
notFull.await();
items[putptr] = x;
if (++putptr == items.length) putptr = 0;
++count;
notEmpty.signal();
} finally { lock.unlock(); }
}
public Object take() throws InterruptedException {
lock.lock(); try {
while (count == 0)
notEmpty.await();
Object x = items[takeptr];
if (++takeptr == items.length) takeptr = 0;
--count;
notFull.signal();
return x;
} finally { lock.unlock(); }
}
}
不要忘记回来点赞哦!!