生产者和消费者问题是从操作系统中的许多实际同步问题中抽象出来的具有
代表性的问题。它反映了操作系统中典型的同步例子.
生产者进程(进程由多个线程组成)生产信息,例如它可以是计算进程。消费
者进程使用信息,它可以是输出打印进程。由于生产者和消费者彼此独立,且运
行速度不确定,所以很可能出现生产者已产生了信息而消费者却没有来得及接受
信息这种情况。为此,需要引入由一个或者若干个存储单元组成的临时存储区,
以便存放生产者所产生的信息,平滑进程间由于速度不确定所带来的问题。这个
临时存储区叫做缓冲区,通常用一维数组来表示。
由一个或若干个存储单元组成的缓冲区叫作“有穷缓冲区”。下面我们来分
析一下有穷缓冲的生产者和消费者的例子。
假设有多个生产者和多个消费者,它们共享一个具有n个存储单元的有穷缓冲
区Buffer(0……n-1),这是一个环形队列。其队尾指针Rear指向当前信息应存放
的位置(Buffer[Rear]),队首指针Front指向当前取出信息的位置(Buffer[front
])。生产者进程总是把信息存放在Buffer[Rear]中,消费者进程则总是从Buffer
[Rear]中取出信息。如果想使生产者进程和消费者进程协调合作,则必须使它们
遵循如下规则:
1) 只要缓冲区有存储单元,生产者都可往其中存放信息;当缓冲区已满时,
若任意生产者提出写要求,则都必须等待;
2) 只要缓冲区中有消息可取,消费者都可从缓冲区中取出消息;当缓冲区为
空时,若任意消费者想取出信息,则必须等待;
3) 生产者们和消费者们不能同时读、写缓冲区。
用JAVA 实现“生产者-消费者”问题的代码如下:
代表性的问题。它反映了操作系统中典型的同步例子.
生产者进程(进程由多个线程组成)生产信息,例如它可以是计算进程。消费
者进程使用信息,它可以是输出打印进程。由于生产者和消费者彼此独立,且运
行速度不确定,所以很可能出现生产者已产生了信息而消费者却没有来得及接受
信息这种情况。为此,需要引入由一个或者若干个存储单元组成的临时存储区,
以便存放生产者所产生的信息,平滑进程间由于速度不确定所带来的问题。这个
临时存储区叫做缓冲区,通常用一维数组来表示。
由一个或若干个存储单元组成的缓冲区叫作“有穷缓冲区”。下面我们来分
析一下有穷缓冲的生产者和消费者的例子。
假设有多个生产者和多个消费者,它们共享一个具有n个存储单元的有穷缓冲
区Buffer(0……n-1),这是一个环形队列。其队尾指针Rear指向当前信息应存放
的位置(Buffer[Rear]),队首指针Front指向当前取出信息的位置(Buffer[front
])。生产者进程总是把信息存放在Buffer[Rear]中,消费者进程则总是从Buffer
[Rear]中取出信息。如果想使生产者进程和消费者进程协调合作,则必须使它们
遵循如下规则:
1) 只要缓冲区有存储单元,生产者都可往其中存放信息;当缓冲区已满时,
若任意生产者提出写要求,则都必须等待;
2) 只要缓冲区中有消息可取,消费者都可从缓冲区中取出消息;当缓冲区为
空时,若任意消费者想取出信息,则必须等待;
3) 生产者们和消费者们不能同时读、写缓冲区。
用JAVA 实现“生产者-消费者”问题的代码如下:
//----------------------------------------------------
// 商品
class Goods {
private int id;
public Goods(int id) { this.id = id; }
public String toString() {
return "Goods: " + id;
}
}
//----------------------------------------------------
// 装东西的容器
class Stack {
private int index = 0;
private Goods[] buffer = new Goods[5]; // 生产者和消费者共享的有界缓冲区
public synchronized void push(Goods goods) {
while(index == buffer.length) {
try {
this.wait();
} catch (InterruptedException e) { e.printStackTrace(); }
}
this.notify();
buffer[index] = goods;
index++;
}
public synchronized Goods pop() {
while(index == 0) {
try {
this.wait();
} catch (InterruptedException e) { e.printStackTrace(); }
}
this.notify();
index--;
return buffer[index];
}
}
//----------------------------------------------------
// 生产者线程
class Producer implements Runnable {
private Stack s = null;
public Producer(Stack s) { this.s = s; }
public void run() {
for(int i = 0; i <= 10; i++) {
Goods g = new Goods(i);
s.push(g);
System.out.println("生产了 " + g);
try {
Thread.sleep(1000);
} catch (InterruptedException e) { e.printStackTrace(); }
}
}
}
//----------------------------------------------------
// 消费者线程
class Consumer implements Runnable {
private Stack s = null;
public Consumer(Stack s) { this.s = s; }
public void run() {
for(int i = 0; i <= 10; i++) {
Goods g = s.pop();
System.out.println("消费了 " + g);
try {
Thread.sleep(1000);
} catch (InterruptedException e) { e.printStackTrace(); }
}
}
}
//----------------------------------------------------
// 主方法
public class ProducerConsumer {
public static void main(String[] args) {
Stack s = new Stack();
Producer p = new Producer(s);
Consumer c = new Consumer(s);
new Thread(p).start();
new Thread(c).start();
}
}