生产者消费者问题
生产者消费者问题是一个多线程同步的问题。
1.生产者生产一定数量的数据放到缓冲区,然后继续生产
2.消费者在缓冲区中消耗这些数据
!!!要保证生产者在缓冲区满时存放数据
!!!要保证消费者在缓冲区空时消耗数据
具体实现
1.采用信号
2.加锁机制
这里用wait() / notify()方法实现
- 当缓冲区满的时候,生产者停止执行,让其他线程进行
- 当缓冲区空的时候,消费者停止执行,让其他线程执行
- 当生产者向缓冲区放入一个产品时,向其他等待的线程发出可执行的通知,同时放弃锁,使自己处于等待状态;
- 当消费者从缓冲区取出一个产品时,向其他等待的线程发出可执行的通知,同时放弃锁,使自己处于等待状态。
仓库Storage
package producer;
import java.util.LinkedList;
public class Storage {
//仓库容量
private final int MAX_SIZE = 10;
//仓库存储的载体
private LinkedList<Object> list= new LinkedList<>();
//生产方法
public void produce(){
synchronized (list){
//判断仓库是否满,满则进入wait阶段
while (list.size()+1 >MAX_SIZE){
System.out.println("生产者"+Thread.currentThread().getName()+"仓库已经满了");
try {
list.wait();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
//没有满则可以生产
list.add(new Object());
System.out.println("生产者"+Thread.currentThread().getName()+"生产了一个产品,现在库存有"+list.size());
list.notifyAll();
}
}
//消费方法
public void consume(){
synchronized (list){
//当库存为0则不让消费
while (list.size()==0){
System.out.println("消费者是"+Thread.currentThread().getName()+"仓库容量为空");
try {
list.wait();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
//不是空则可以消费
list.remove();
System.out.println("消费者"+Thread.currentThread().getName()+"消费了一个产品,现在还剩有产品"+list.size());
list.notifyAll();
}
}
}
生产者
package producer;
public class Producer implements Runnable{
//生产者类
private Storage storage;
public Producer(){
}
public Producer(Storage storage){
this.storage = storage;
}
@Override
public void run() {
while (true){
try {
Thread.sleep(1000);
storage.produce();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
}
消费者
package producer;
public class Consumer implements Runnable{
//消费者
private Storage storage;
public Consumer(){
}
public Consumer(Storage storage){
this.storage = storage;
}
@Override
public void run() {
while (true){
try {
Thread.sleep(3000);
storage.consume();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
}
主方法
package producer;
public class Main {
public static void main(String[] args) {
Storage storage = new Storage();
Thread p1 = new Thread(new Producer(storage));
Thread p2 = new Thread(new Producer(storage));
Thread p3 = new Thread(new Producer(storage));
Thread c1 = new Thread(new Consumer(storage));
Thread c2 = new Thread(new Consumer(storage));
Thread c3 = new Thread(new Consumer(storage));
p1.start();
p2.start();
p3.start();
c1.start();
c2.start();
c3.start();
}
}
运行结果
一个生产者线程运行produce方法,睡眠1s;一个消费者运行一次consume方法,睡眠3s。
notifyAll()方法可使所有正在等待队列中等待同一共享资源的“全部”线程从等待状态退出,进入可运行状态。此时,优先级最高的哪个线程最先执行,但也有可能是随机执行的,这要取决于JVM虚拟机的实现。