java 生产者和消费者

//生产者和消费者
public class ProducerConsumer {
 public static void main(String[] args) {
  SyncStack ss = new SyncStack();
  Producer p = new Producer(ss); // 把蓝子传入
  Consumers c = new Consumers(ss);  // 把蓝子传入
  new Thread(p).start();// 三个大师傅在生产窝头
//  new Thread(p).start();
//  new Thread(p).start();
  new Thread(c).start();// 三个食客在吃窝头
//  new Thread(c).start();
//  new Thread(c).start();
 }
}

// 构造窝头类
class WoTou {
 int id; // 用来标示是第几个
 WoTou(int id) {
  this.id = id;
 }
 public String toString() { // 重写toString方法 返回值是String字符串+id号
  return "WoTou : " + id;
 }
}

// 用栈来模拟蓝子,先进的后出  生产者消费者线程对象访问同一个蓝子
class SyncStack {
 int index = 0; // 指向当前窝头的向上一个元素
 WoTou[] arrWT = new WoTou[6]; // 蓝子的容量 构造一个窝头类数组 数组是有固定容量的
 
 public synchronized void push(WoTou wt) { // 放窝头的方法,传进去一个窝头对象 不能被打断,所以加同步 一个生产者在生产的时候,其他生产者就不能生产了,但是可以消费
  while(index == arrWT.length) { // 写while,防止被Interrupted之后执行后面的语句.即使被打断了,还要进入循环判断是否已经满了
   try {
    this.wait(); // 阻塞线程,index不在增加了.this.wait方法,让当前访问该对象的线程等待 阻塞住 只有锁定的对象才有资格wait.wait的过程中锁就不在归当前对象所有了.而sleep不同.睡着了也要抱着锁
   } catch (InterruptedException e) {
    e.printStackTrace();
   }
  }
  this.notifyAll();// 叫醒其他正在当前对象上wait的线程对象.哪个线程在这儿等呢,就叫醒哪个线程.叫醒wait中的消费者,可以消费了.这个方法写在while(index == arrWT.length){}外面是说生产了一个就通知消费者可以吃了.如果是写在里面,则是生产到了6个才通知消费者
  arrWT[index] = wt; // 把传进入的窝头对象赋给窝头类数组存放
  index ++; // 放进去一个窝头.栈顶指针加1
 }
 
 public synchronized WoTou pop() { // 出窝头方法,返回值是窝头对象 不能被打断,所以加同步 一个消费者在消费的时候,其他消费者就不能消费了.但是可以生产
  while(index == 0) { // 当蓝子空了
   try {
    this.wait(); // 需要被叫醒
   } catch (InterruptedException e) {
    e.printStackTrace();
   }
  }
  this.notifyAll();// 叫醒wait中的生产者,可以继续生产了.已经吃了一个了
  index--; // 拿出去了.窝头减1
  return arrWT[index]; // 拿到窝头,返回去.拿到刚才放进去的.因为是栈
 }
}

// 生产者线程 因为有很多个大师傅在生产窝头
class Producer implements Runnable {
 SyncStack ss = null; // 需要知道往哪个蓝子里扔东西.所以拥有这个蓝子的一个引用
 Producer(SyncStack ss) { // 构造方法,往哪个蓝子里放窝头
  this.ss = ss;
 }
 
 public void run() {
  for(int i=0; i<20; i++) { // 每个大师傅生产20个窝头
   WoTou wt = new WoTou(i); // 构造方法里把i的值传进去,第几个窝头
   ss.push(wt);
   System.out.println("生产了:" + wt);
   try {
    Thread.sleep((int)(Math.random() * 50)); // 随机时间睡眠
   } catch (InterruptedException e) {
    e.printStackTrace();
   }   
  }
 }
}

// 消费者线程 有很多个食客在吃窝头
class Consumers implements Runnable {
 SyncStack ss = null;
 Consumers(SyncStack ss) { // 从哪个蓝子里拿窝头
  this.ss = ss;
 }
 
 public void run() {
  for(int i=0; i<20; i++) { // 允许每个食客吃20个窝头
   WoTou wt = ss.pop(); // pop方法,返回值是窝头对象
   System.out.println("消费了: " + wt);
   try {
    Thread.sleep((int)(Math.random() * 1000));
   } catch (InterruptedException e) {
    e.printStackTrace();
   }   
  }
 }
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值