生产者-消费者模型
生产者-消费者(producer-consumer)问题,称之为有界缓冲区问题,两个线程共享一个固定的大小的缓冲区
其中一个是生产者、生产消息存放到缓冲区、另一个是消费者,在缓冲区取出消息
具体说明:
生产者生产数据到缓存区,消费者从缓存去取数据
如果缓存区满了,则生产者线程阻塞
如果缓存区空了,消费者线程阻塞
将阻塞的线程在一定的时间进行唤醒,通过线程的通信机制来唤醒,对于生产者线程,他的唤醒是有消费者有消费时就可以通知唤醒,同样,对于消费者线程,他的唤醒是有生产者生产了数据后通知唤醒
通过Synchronized和wait、notify、notifyAll实现
生产者:
public class Producer1 implements Runnable {
//仓库
private LinkedList <Integer> cap;
private Random random = new Random();
public Producer1(LinkedList <Integer> cap) {
this.cap = cap;
}
@Override
public void run() {
while (true) {
synchronized (cap) {
try {
//仓库是否满
while (cap.size() == 3) {
cap.wait();
}
//生产者生产
int value = random.nextInt(1000);
System.out.println("生产者生产:"+value);
cap.addLast(value);
//通知消费者,使用notify是否合适?,给定notifyAll实际上要通知到生产者、消费者
cap.notifyAll();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
}
}
消费者:
public class Consumer1 implements Runnable {
private LinkedList <Integer> cap;
public Consumer1(LinkedList <Integer> cap) {
this.cap = cap;
}
@Override
public void run() {
while (true) {
//仓库是生产者和消费者互斥使用
synchronized (cap) {
try {
//判断是否可以消费
while (cap.size() == 0) {
cap.wait();
}
//消费者消费
Integer value = cap.removeFirst();
System.out.println("消费者消费:"+value);
//通知生产者
cap.notifyAll();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
}
}
通过Lock实例和Condition实现
生产者:
public class Producer2 implements Runnable {
//仓库
private LinkedList<Integer> cap;
//Lock锁实例
private ReentrantLock lock;
//生产通知
private Condition noFull;
//消费通知
private Condition noEmpty;
private Random random = new Random();
public Producer2(LinkedList <Integer> cap, ReentrantLock lock, Condition noFull, Condition noEmpty) {
this.cap = cap;
this.lock = lock;
this.noFull = noFull;
this.noEmpty = noEmpty;
}
@Override
public void run() {
while (true) {
//加锁
lock.lock();
try {
//判断是否可生产
while (cap.size() == 3) {
noFull.await();
}
int value = random.nextInt(1000);
cap.addLast(value);
System.out.println("生产者生产:"+value);
//通知消费者消费
noEmpty.signal();
}catch (Exception e) {
} finally {
//释放锁
lock.unlock();
}
}
}
}
消费者:
public class Consumer2 implements Runnable{
//仓库
private LinkedList<Integer> cap;
//Lock锁实例
private ReentrantLock lock;
//生产通知
private Condition noFull;
//消费通知
private Condition noEmpty;
public Consumer2(LinkedList <Integer> cap, ReentrantLock lock, Condition noFull, Condition noEmpty) {
this.cap = cap;
this.lock = lock;
this.noFull = noFull;
this.noEmpty = noEmpty;
}
@Override
public void run() {
while (true) {
//加锁
lock.lock();
try {
//判断是否可消费
while (cap.size() == 0) {
noEmpty.await();
}
//消费
Integer value = cap.removeFirst();
System.out.println("消费者消费:"+value);
//通知生产者生产
noFull.signal();
}catch (Exception e) {
} finally {
//释放锁
lock.unlock();
}
}
}
}