题目:
编写一个基于多线程的生产者/消费者程序,各产生10个生产者和消费者线程,共享一个缓冲区队列(长度自设),生产者线程将产品放入缓冲区,消费者线程从缓冲区取出产品。
思路:
题目中很明显可以看出有3个类:生产者,消费者,缓冲区。
缓冲区:
缓冲区(Store)用于存放产品,经题目提示(长度自设),我们可以给缓冲区类设计2个属性:仓库的最大容量——MAX_SIZE
和当前的货物数量——count
。
其次,缓冲区用来存货、取货,所以我们设计2个函数:存货函数——add()
和取货函数——remove()
。并且用监视器和synchronized来线程同步,保证其原子性。
最后,在上面两个函数中,我们还需要用到wait和notifyAll实现线程间同步通信。
对于add()
方法:每调用一次,就增加一个货物,那么就通知notifyAll所有取货的线程可以开始运行了。但是如果某次调用发现缓存区的货物满了,那么就用wait方法开始等待缓存区空出来一个位置。
对于remove()
方法:也是同理,只是操作相反。
public class Store {
private final int MAX_SIZE;//仓库的最大容量
private int count;//当前的货物数量
public Store(int n){//初始化最大容量的构造方法
MAX_SIZE = n;
count = 0;
}
public synchronized void add(){//往仓库加货物的方法
while(count >= MAX_SIZE){//每次执行都判断仓库是否已满
System.out.println("已经满了");
try {
this.wait();//如果满了,就进入等待池
} catch (Exception e) {
e.printStackTrace();
}
}
count++;//数量加1
//打印当前仓库的货物数量
System.out.println(Thread.currentThread().toString()+"put"+count);
//仓库中已经有东西可以取了,则通知所有的消费者线程来拿
this.notifyAll();
}
public synchronized void remove(){//从仓库拿走货物的方法
while(count<=0){
System.out.println("空了");//每次执行都判断仓库是否为空
try {
this.wait();//如果为空,就进入等待池
} catch (Exception e) {
e.printStackTrace();
}
}
//打印当前仓库的货物数量
System.out.println(Thread.currentThread().toString()+"get"+count);
count--;//数量减1
//仓库还没装满,通知生产者添加货物
this.notifyAll();
}
}
生产者:
生产者类的功能就是生产产品,那么就是重写run()
方法。
public class Producer extends Thread {
private Store s;
public Producer(Store s){
this.s = s;
}
public void run(){//线程方法
while(true){//循环
s.add();//往仓库加货物
try {
Thread.sleep(1000);//设置线程休息1s
} catch (Exception e) {
e.printStackTrace();
}
}
}
}
消费者:
消费者类的功能就是消费产品,那么也是重写run()
方法。
public class Consumer extends Thread {
private Store s;
public Consumer(Store s){
this.s = s;
}
public void run(){//线程方法
while(true){//循环
s.remove();//从仓库取走货物
try {
Thread.sleep(1500);//设置线程休息1.5s
} catch (Exception e) {
e.printStackTrace();
}
}
}
}
最后写一个主函数调用:
public class RunStore {
public static void main(String[] args) {
Store s = new Store(5);
//创建两个生产者和两个消费者
Thread pro1 = new Producer(s);
Thread con1 = new Consumer(s);
Thread pro2 = new Producer(s);
Thread con2 = new Consumer(s);
pro1.setName("producer1");
con1.setName("consumer1");
pro2.setName("producer2");
con2.setName("consumer2");
//启动线程
pro1.start();
con1.start();
pro2.start();
con2.start();
}
}
运行结果: