进程同步问题——生产者、消费者问题
生产者、消费者问题是操作系统中个著名的进程同步问题。一般是指: 有一群生产者进程在生产产品,并将此产品提供给消费者进程去消费。为使生产者进程和消费者进程能并发执行,在它们之间设置一个缓冲区, 生产者进程可将它所产的产品放入一个缓冲区中,消费者进程可从一个缓冲区取得一个产品消费。尽管所有的生产者进程和消费者进程都是以异步的方式运行的,但它们之间必须保持同步,即不允许消费者进程到一个空缓冲区去取产品,也不允许生产者进程向一个已装有消息、 但尚未取走产品的满缓冲区投放产品。这里将“进程”换成“线程”,问题仍然成立。下面要做由事情就是用线程来模拟这一过程。
在这里设计一个公共类,信号量和共享资源都以静态成员变量的形式存于该对象中。在创建线程对象时,将这个公共对象床底进去,作为线程对象的私有数据。这样无论哪个线程对象,访问的都是同一个信号量和共享资源。
公共类的实现:
public class Common { //公共线程类
private int production[];
private int count; //实际产品数目
private int BUFFER_SIZE=6; //缓冲区大小
public Common(){
production=new int[BUFFER_SIZE];
count=0;
}
//从缓冲区取数据
public synchronized int get(){
int result;
//循环检测缓冲区是否可用
while (count<=0) {
try {
wait(); //等待
} catch (InterruptedException e) {
e.printStackTrace();
}
}
result=production[--count];
notifyAll();
return result;
}
//向缓冲区写数据
public synchronized void put(int newProduct){
//循环检测缓冲区是否可用
while (count>=BUFFER_SIZE){
try {
wait();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
production[count++]=newProduct;
notifyAll();
}
}
消费者线程:
public class Consumer extends Thread {
private Common common;
public Consumer(Common thisCommon){
common=thisCommon;
}
public void run(){
int i,production;
for(i=1;i<=20;i++){
production=common.get();
System.out.println("得到的数据是:"+production);
try {
sleep(10);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
}
生产者线程:
public class Producer extends Thread {
private Common common;
public Producer(Common thisCommon){
common=thisCommon;
}
public synchronized void run(){
for(int i=1;i<=10;i++){
common.put(i);
System.out.println("生产的数据是:"+i);
try{
sleep(10);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
}
主线程:
public class Producer_Consumer {
public static void main(String[] args){
Common common=new Common();
//两个生产者
Producer producer1=new Producer(common);
Producer producer2=new Producer(common);
//一个消费者
Consumer consumer=new Consumer(common);
producer1.start();
producer2.start();
consumer.start();
}
}
运行结果截图: