生产者和消费者问题
生产者消费者问题(英语:Producer-consumer problem),也称有限缓冲问题(英语:Bounded-buffer problem),是一个多进程同步问题的经典案例。该问题描述了共享固定大小缓冲区的两个进程——即所谓的“生产者”和“消费者”——在实际运行时会发生的问题。生产者的主要作用是生成一定量的数据放到缓冲区中,然后重复此过程。与此同时,消费者也在缓冲区消耗这些数据。该问题的关键就是要保证生产者不会在缓冲区满时加入数据,消费者也不会在缓冲区中空时消耗数据。
1.1java提供的机制
均是Object类中的方法,都只能在同步方法和同步代码块中使用。
void |
notify() 唤醒一个在这个对象的监视器上等待的单个线程。 |
---|---|
void |
notifyAll() 唤醒正在等待此对象监视器上的所有线程。 |
void |
wait() 使当前线程等待另一个线程调用此对象的方法或 notify() notifyAll() 方法。 |
---|---|
void |
wait(long timeout) 使当前线程等待另一个线程调用此对象的方法或 notify() notifyAll() 方法,或一个指定的时间流逝。 |
void |
wait(long timeout, int nanos) 使当前线程等待另一个线程调用此对象的方法或 notify() notifyAll() 方法,或者其他某个线程中断当前线程,或一定量的实际时间已经过去了。 |
1.2提供缓冲区
/**
* 管程法解决生产者消费者问题
*/
public class TestBuffer {
public static void main(String[] args) {
//创建缓冲区
BufferSynContainer container = new BufferSynContainer();
new Producer(container).start();
new Consumer(container).start();
}
}
class Producer extends Thread{
BufferSynContainer buffer;
public Producer(BufferSynContainer buffer){
this.buffer = buffer;
}
//生产
public void run() {
for (int i = 0; i < 100; i++) {
buffer.push(new Chicken(i+1));
System.out.println("生产了"+(i+1)+"只鸡");
}
}
}
class Consumer extends Thread{
BufferSynContainer buffer;
public Consumer(BufferSynContainer buffer){
this.buffer = buffer;
}
//消费
public void run() {
for (int i = 0; i < 100; i++) {
System.out.println("消费了-->"+buffer.pop().getId()+"只鸡");
}
}
}
//产品
class Chicken{
private int id;
public Chicken(int id) {
this.id = id;
}
public int getId() {
return id;
}
public void setId(int id) {
this.id = id;
}
}
class BufferSynContainer{
//缓冲区大小
Chicken[] chickens = new Chicken[10];
int count = 0;
//生产者生产
public synchronized void push(Chicken chicken){
//容器满了,生产者等待
if (count==chickens.length){
try {
this.wait();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
//放入缓冲区
chickens[count] = chicken;
count++;
//通知消费者可以消费了
this.notifyAll();
}
//消费者消费产品
public synchronized Chicken pop(){
//看缓冲区中是否有数据
if (count<=0){
try {
this.wait();//没有产品等待
} catch (InterruptedException e) {
e.printStackTrace();
}
}
//如果有数据进行消费
count--;
Chicken chicken = chickens[count];
//吃完了,通知生产者生产
this.notifyAll();
return chicken;
}
}
1.3信号灯法——并发协作
semaphore mutex = 1;
2 semaphore fillCount = 0;
3 semaphore emptyCount = BUFFER_SIZE;
4
5 procedure producer() {
6 while (true) {
7 item = produceItem();
8 down(emptyCount);
9 down(mutex);
10 putItemIntoBuffer(item);
11 up(mutex);
12 up(fillCount);
13 }
14 }
15 procedure consumer() {
16 while (true) {
17 down(fillCount);
18 down(mutex);
19 item = removeItemFromBuffer();
20 up(mutex);
21 up(emptyCount);
22 consumeItem(item);
23 }
24 }