1、生产者仅仅在仓储未满时候生产,仓满则停止生产。
2、消费者仅仅在仓储有产品时候才能消费,仓空则等待。
3、当消费者发现仓储没产品可消费时候会通知生产者生产。
4、生产者在生产出可消费产品时候,应该通知等待的消费者去消费
使用Object的wait()/notify()方法
1.wait():当缓存区已满/已空时,生产者/消费者线程自己停止自己的执行,放弃锁,使自己处于等待状态,让其他进程执行。
2.notify():放生产者/消费者向缓存区放入/取出一个产品时,向其等待的线程发出可执行的通知,同时放弃锁,使自己处于等待状态。
这个模式有两种写法:管程法 和 信号灯法
附上代码(管程法):
package nsu.edu.one;
/**
* 生产者消费者模式--->管程法
* 模拟生产馒头和消费馒头
*/
public class Main {
public static void main(String[] args) {
Buffer buffer = new Buffer();
new Producer_one(buffer).start();
new Producer_one(buffer).start();
new Consumer_one(buffer).start();
}
}
//生产者
class Producer_one extends Thread{
Buffer buffer;
public Producer_one(Buffer buffer) {
this.buffer = buffer;
}
public void run() { //生产
int i=0; //给馒头编号
while(true)
{
i++;
try {
Thread.sleep(200); //生产一个耗时0.2S
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
System.out.println("生产第"+i+"个馒头");
buffer.push(new Bread(i));
}
}
}
//消费者
class Consumer_one extends Thread{
Buffer buffer;
public Consumer_one(Buffer buffer) {
this.buffer = buffer;
}
public void run() { //消费
while(true)
{
try {
Thread.sleep(200); //消费一个耗时0.2S
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
System.out.println("消费第"+buffer.consumption().id+"个馒头");
buffer.consumption();
}
}
}
//缓冲区
class Buffer{
Bread[] warehouse = new Bread[10]; //创建缓冲数组 大小为10
int count = 0; //计数
//有两种操作 消费和生产
public synchronized Bread consumption() { //消费
//什么时候不可以消费
if(count <= 0)
{
try {
System.out.println("仓库空了,不能消费"+count);
this.wait();
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
//有数据可以消费
count--;
Bread bread = warehouse[count];
//消费完了 通知生产者可以生产
this.notifyAll();
return bread;
}
public synchronized void push(Bread bread){ //生产
//何时不能生产? 没有空间不能生产
if(count == warehouse.length) {
try {
System.out.println("仓库满了,不能生产"+count);
this.wait();
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
//有空间可以生产
warehouse[count] = bread;
count++;
this.notifyAll();
}
}
//馒头
class Bread {
int id; //馒头编号
public Bread(int id) {
this.id = id;
}
}
附上代码(信号灯法):
/**
* 生产者消费者模式--->信号灯法
*
*/
public class Main {
public static void main(String[] args)
{
Signal signal = new Signal();
new Producer_one(signal).start();
new Consumer_one(signal).start();
}
}
//生产者
class Producer_one extends Thread{
Signal signal;
String str;
public Producer_one(Signal signal) {
this.signal = signal;
}
public void run() {
for(int i=0;i<100;i++) {
signal.push();
}
}
}
//消费者
class Consumer_one extends Thread{
Signal signal;
String str;
public Consumer_one(Signal signal) {
this.signal = signal;
}
public void run() {
for(int i=0;i<100;i++) {
signal.pop();
}
}
}
//信号灯
class Signal{
boolean flug = false; //新号灯
//存储
public synchronized void push() {
if(!flug) { //如果新号灯为真,说明可以生产
try { //反之则等待
this.wait();
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
//开始生产
System.out.println("生产");
flug=!flug; //生产完了,新号灯转变状态
this.notifyAll();
}
//消费
public synchronized void pop() {
if(flug) { //如果新号灯为真,说明需要等待
try {
this.wait();
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
//消费
System.out.println("消费");
flug=!flug; //生产完了,新号灯转变状态
this.notifyAll();
}
}
努力呀!