第一次接触生产消费者问题是在操作系统课上,当时是用的信号量来解决这个问题,为了实现互斥搞得挺麻烦。今天用Java多线程来实现就简单多了。
1.存储类
用于存放生产的东西的类。
public class Store {
private int MAX_NUM = 0;//仓库最大容量
private int count = 0;//仓库现有容量
public Store(int num){
this.MAX_NUM = num;
}
synchronized public void add(){
while(count>=MAX_NUM){
System.out.println("It's full.\n");
try {
this.wait();//进入等待池
} catch (InterruptedException e) {
e.printStackTrace();
}
}
count++;
System.out.println(Thread.currentThread().getName()+" count = "+count);
this.notifyAll();//通知所有消费者线程,将它们从线程池唤醒
}
synchronized public void remove(){
while(count<=0){
System.out.println("It's Empty.\n");
try {
this.wait();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
count--;
System.out.println(Thread.currentThread().getName()+" count = "+count);
this.notify();//唤醒某一个生产者线程
}
}
在这个类里就进行实现对存储区域操作的互斥,用了synchronized关键字和wait,notify等函数。
2.消费者和生产者线程实现
消费者线程执行出库操作:
public class Consumer extends Thread{
Store s;
public Consumer(Store s) {
this.s = s;
}
@Override
public void run() {
while(true){
s.remove();
try {
Thread.sleep(1500);//为了看得更清楚
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
}
生产者线程执行入库操作:
public class Producer extends Thread{
Store s;
public Producer(Store s) {
this.s = s;
}
@Override
public void run() {
while(true){
s.add();
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
}
以上没什么解释的,注意生产者比消费者快。
3.实现这个场景
在Main方法中:
声明了各两个对象线程,仓库容量为3:
public static void main(String[] args) {
Store s = new Store(3);
Producer p1 = new Producer(s);
Producer p2 = new Producer(s);
Consumer c1 = new Consumer(s);
Consumer c2 = new Consumer(s);
p1.setName("p1");
p2.setName("p2");
c1.setName("c1");
c2.setName("c2");
p1.start();
p2.start();
c1.start();
c2.start();
}
执行结果:
看起来消费者是比生产者要慢一些,所以难得看到空。