java线程之生产者消费者问题
2013-07-26 11:07
375 查看
public class ProducerConsumer { public static void main(String[] args) { SyncStack ss = new SyncStack();// new一个容器用于装窝头 Producer p = new Producer(ss);// new一个生产者线程,参数指明往哪个容器内生产 Consumer c = new Consumer(ss);// new一个消费者线程,参数指明从哪个容器内消费 // 上面两个线程访问的是同一个容器对象 new Thread(p).start();// 启动两个线程 new Thread(c).start(); } } // 实现窝头类 class WoTou { int id;// 给每个窝头一个标记 WoTou(int id) {// 写其构造方法,传递的参数是将被新建的对象的id this.id = id; } public String toString() {// 重写其toString方法,用于下面将对象输出 return "WoTou" + id; } } // 实现容器类,先进后出,stack class SyncStack { int index = 0;// 用index标记现在装到第几个了 static int num = 0;// 用于统计容器中共有几个窝头 WoTou[] arrWT = new WoTou[6];// 用一个对象数组来模拟容器,该容器只能装WoTou类对象,设置容量为6 // 实现往容器中放窝头的方法 public synchronized void push(WoTou wt) {// 传递的参数是WoTou类对象wt while (num == arrWT.length) {// 如果当前容器满了,wait try { System.out.println("满了,请消费!!"); this.wait();// 让锁定当前对象的当前线程wait,并释放锁 } catch (InterruptedException e) { e.printStackTrace(); } } arrWT[index] = wt;// 将窝头装进容器 num += 1;// 窝头数加1 System.out.println("往容器里放进了" + wt); System.out.println("当前容器里有" + num + "个窝头"); index++;// 标记移向下一位置 this.notify();// 放进的动作完成后,叫醒一个现在正在wait在这个对象上的线程 } // 实现拿出窝头的方法 public synchronized void pop() { while (num == 0) {// 如果当前容器空了,wait try { System.out.println("空了,请生产!!"); this.wait();// 让锁定当前对象的当前线程wait,并释放锁 } catch (InterruptedException e) { e.printStackTrace(); } } index--;// 标记移向前一位置 num -= 1;// 窝头数减1 System.out.println("从容器里拿出了" + arrWT[index]); System.out.println("消费了:" + arrWT[index]); System.out.println("当前容器里有" + num + "个窝头"); this.notify();// 拿出的动作完成后,叫醒一个现在正在wait在这个对象上的线程 } } // 实现生产者类 class Producer implements Runnable { SyncStack ss = null;// 新建容器用于装窝头 Producer(SyncStack ss) {// 实现其构造函数,指明往哪个容器里生产 this.ss = ss; } public void run() {// 实现Runnable接口就必须重写其run方法 for (int i = 0; i < 20; i++) {// 假设每个生产者最多生产20个窝头 WoTou wt = new WoTou(i); // 调用WoTou类的构造方法生产窝头wt,传递的参数是wt的id System.out.println("生产了:" + wt);// 每生产一个就打印一句,输出对象wt的时候,其实是输出object的toString方法返回的值 ss.push(wt);// 调用容器ss的push方法将窝头wt放进容器ss,传递的参数是WoTou类对象wt try { Thread.sleep((int) (Math.random() * 2));// 生产一个后睡眠一下 } catch (InterruptedException e) { e.printStackTrace(); } } } } // 实现消费者类 class Consumer implements Runnable { SyncStack ss = null; // 指明从哪个容器里消费 Consumer(SyncStack ss) { // 指明到哪个容器里消费 this.ss = ss; } public void run() { // 实现Runnable接口就必须重写其run方法 for (int i = 0; i < 20; i++) { // 假设每个消费者最多消费20个窝头 ss.pop(); // 调用容器对象ss的pop方法消费窝头,pop方法的返回值是一个WoTou类对象 try { Thread.sleep((int) (Math.random() * 1000)); } catch (InterruptedException e) { e.printStackTrace(); } } } }
执行结果有如下两种类型:
类型一:
生产了:WoTou0
往容器里放进了WoTou0
当前容器里有1个窝头
生产了:WoTou1
往容器里放进了WoTou1
当前容器里有2个窝头
生产了:WoTou2
往容器里放进了WoTou2
当前容器里有3个窝头
生产了:WoTou3
往容器里放进了WoTou3
当前容器里有4个窝头
从容器里拿出了WoTou3
消费了:WoTou3
当前容器里有3个窝头
生产了:WoTou4
往容器里放进了WoTou4
当前容器里有4个窝头
生产了:WoTou5
往容器里放进了WoTou5
当前容器里有5个窝头
生产了:WoTou6
往容器里放进了WoTou6
当前容器里有6个窝头
生产了:WoTou7
满了,请消费!!
从容器里拿出了WoTou6
消费了:WoTou6
当前容器里有5个窝头
往容器里放进了WoTou7
当前容器里有6个窝头
生产了:WoTou8
满了,请消费!!
从容器里拿出了WoTou7
消费了:WoTou7
当前容器里有5个窝头
往容器里放进了WoTou8
当前容器里有6个窝头
生产了:WoTou9
满了,请消费!!
从容器里拿出了WoTou8
消费了:WoTou8
当前容器里有5个窝头
往容器里放进了WoTou9
当前容器里有6个窝头
生产了:WoTou10
满了,请消费!!
从容器里拿出了WoTou9
消费了:WoTou9
当前容器里有5个窝头
往容器里放进了WoTou10
当前容器里有6个窝头
生产了:WoTou11
满了,请消费!!
从容器里拿出了WoTou10
消费了:WoTou10
当前容器里有5个窝头
往容器里放进了WoTou11
当前容器里有6个窝头
生产了:WoTou12
满了,请消费!!
从容器里拿出了WoTou11
消费了:WoTou11
当前容器里有5个窝头
往容器里放进了WoTou12
当前容器里有6个窝头
生产了:WoTou13
满了,请消费!!
从容器里拿出了WoTou12
消费了:WoTou12
当前容器里有5个窝头
往容器里放进了WoTou13
当前容器里有6个窝头
生产了:WoTou14
满了,请消费!!
从容器里拿出了WoTou13
消费了:WoTou13
当前容器里有5个窝头
往容器里放进了WoTou14
当前容器里有6个窝头
生产了:WoTou15
满了,请消费!!
从容器里拿出了WoTou14
消费了:WoTou14
当前容器里有5个窝头
往容器里放进了WoTou15
当前容器里有6个窝头
生产了:WoTou16
满了,请消费!!
从容器里拿出了WoTou15
消费了:WoTou15
当前容器里有5个窝头
往容器里放进了WoTou16
当前容器里有6个窝头
生产了:WoTou17
满了,请消费!!
从容器里拿出了WoTou16
消费了:WoTou16
当前容器里有5个窝头
往容器里放进了WoTou17
当前容器里有6个窝头
生产了:WoTou18
满了,请消费!!
从容器里拿出了WoTou17
消费了:WoTou17
当前容器里有5个窝头
往容器里放进了WoTou18
当前容器里有6个窝头
生产了:WoTou19
满了,请消费!!
从容器里拿出了WoTou18
消费了:WoTou18
当前容器里有5个窝头
往容器里放进了WoTou19
当前容器里有6个窝头
从容器里拿出了WoTou19
消费了:WoTou19
当前容器里有5个窝头
从容器里拿出了WoTou5
消费了:WoTou5
当前容器里有4个窝头
从容器里拿出了WoTou4
消费了:WoTou4
当前容器里有3个窝头
从容器里拿出了WoTou2
消费了:WoTou2
当前容器里有2个窝头
从容器里拿出了WoTou1
消费了:WoTou1
当前容器里有1个窝头
从容器里拿出了WoTou0
消费了:WoTou0
当前容器里有0个窝头
类型二:
生产了:WoTou0
空了,请生产!!
往容器里放进了WoTou0
当前容器里有1个窝头
从容器里拿出了WoTou0
消费了:WoTou0
当前容器里有0个窝头
生产了:WoTou1
往容器里放进了WoTou1
当前容器里有1个窝头
生产了:WoTou2
往容器里放进了WoTou2
当前容器里有2个窝头
生产了:WoTou3
往容器里放进了WoTou3
当前容器里有3个窝头
生产了:WoTou4
往容器里放进了WoTou4
当前容器里有4个窝头
生产了:WoTou5
往容器里放进了WoTou5
当前容器里有5个窝头
生产了:WoTou6
往容器里放进了WoTou6
当前容器里有6个窝头
生产了:WoTou7
满了,请消费!!
从容器里拿出了WoTou6
消费了:WoTou6
当前容器里有5个窝头
往容器里放进了WoTou7
当前容器里有6个窝头
生产了:WoTou8
满了,请消费!!
从容器里拿出了WoTou7
消费了:WoTou7
当前容器里有5个窝头
往容器里放进了WoTou8
当前容器里有6个窝头
生产了:WoTou9
满了,请消费!!
从容器里拿出了WoTou8
消费了:WoTou8
当前容器里有5个窝头
往容器里放进了WoTou9
当前容器里有6个窝头
生产了:WoTou10
满了,请消费!!
从容器里拿出了WoTou9
消费了:WoTou9
当前容器里有5个窝头
往容器里放进了WoTou10
当前容器里有6个窝头
生产了:WoTou11
满了,请消费!!
从容器里拿出了WoTou10
消费了:WoTou10
当前容器里有5个窝头
往容器里放进了WoTou11
当前容器里有6个窝头
生产了:WoTou12
满了,请消费!!
从容器里拿出了WoTou11
消费了:WoTou11
当前容器里有5个窝头
往容器里放进了WoTou12
当前容器里有6个窝头
生产了:WoTou13
满了,请消费!!
从容器里拿出了WoTou12
消费了:WoTou12
当前容器里有5个窝头
往容器里放进了WoTou13
当前容器里有6个窝头
生产了:WoTou14
满了,请消费!!
从容器里拿出了WoTou13
消费了:WoTou13
当前容器里有5个窝头
往容器里放进了WoTou14
当前容器里有6个窝头
生产了:WoTou15
满了,请消费!!
从容器里拿出了WoTou14
消费了:WoTou14
当前容器里有5个窝头
往容器里放进了WoTou15
当前容器里有6个窝头
生产了:WoTou16
满了,请消费!!
从容器里拿出了WoTou15
消费了:WoTou15
当前容器里有5个窝头
往容器里放进了WoTou16
当前容器里有6个窝头
生产了:WoTou17
满了,请消费!!
从容器里拿出了WoTou16
消费了:WoTou16
当前容器里有5个窝头
往容器里放进了WoTou17
当前容器里有6个窝头
生产了:WoTou18
满了,请消费!!
从容器里拿出了WoTou17
消费了:WoTou17
当前容器里有5个窝头
往容器里放进了WoTou18
当前容器里有6个窝头
生产了:WoTou19
满了,请消费!!
从容器里拿出了WoTou18
消费了:WoTou18
当前容器里有5个窝头
往容器里放进了WoTou19
当前容器里有6个窝头
从容器里拿出了WoTou19
消费了:WoTou19
当前容器里有5个窝头
从容器里拿出了WoTou5
消费了:WoTou5
当前容器里有4个窝头
从容器里拿出了WoTou4
消费了:WoTou4
当前容器里有3个窝头
从容器里拿出了WoTou3
消费了:WoTou3
当前容器里有2个窝头
从容器里拿出了WoTou2
消费了:WoTou2
当前容器里有1个窝头
从容器里拿出了WoTou1
消费了:WoTou1
当前容器里有0个窝头
发现第二种类型的第二句输出是错误的,出错原因在哪儿呢?该怎么解决呢?
相关文章推荐
- Java线程通信练习之“生产者/消费者问题”
- Java线程(三)----线程协作-生产者/消费者问题
- Java线程同步实例 生产者 消费者问题分析
- java 线程间通信,多生产者多消费者问题
- 线程通信,生产者消费者问题(Java)
- Java线程之由生产者/消费者问题看线程同步与通信
- Java线程与并发编程实践----等待通知(生产者消费者问题)线程
- Java线程(三):线程协作-生产者/消费者问题
- java生产者消费者问题(线程同步与线程等待的应用)
- JAVA学习笔记(1)_____模拟线程通信之生产者消费者问题
- Java线程(三):线程协作-生产者/消费者问题
- Thinking in Java---线程通信+三种方式实现生产者消费者问题
- [java线程同步]生产者消费者问题demo
- Java基础_线程_多线程_生产者消费者问题
- Java线程(三):线程协作-生产者/消费者问题
- Java线程间的相互通信--生产者消费者问题
- 【Java】线程wait() notify()通信 实现生产者 消费者问题
- Java线程之线程协作(生产者/消费者问题)
- Java 线程的基本概念(模仿生产者与消费者的问题)
- java基础---->线程 生产者消费者问题