1 /** 2 * 2019年8月8日17:42:23 3 * 目的:Java多线程实现生产与消费 4 * @author 张涛 5 * 6 * 多态: 7 * 一个父类的引用既可以指向父类对象 8 * 也可以指向子类对象 9 * 它会根据当前时刻指向的不同 10 * 自动调用该对象里面的属性和方法 11 * 12 * this: 13 * this在构造方法中表示正在构造的对象 14 * this在一般方法中表示正在调用的对象 15 */ 16 17 //构建栈(杯子)类 18 class synstack 19 { 20 //数组相当于货架,每次只能放入6个 21 char[] data = new char[6]; 22 23 //数组当前有效元素个数 24 int cnt = 0; 25 26 //生产方法 27 public synchronized void push(char ch) 28 { 29 //每一次都要判断货架是否满了,如果满了,就wait,唤醒另一个进程 30 while(cnt == data.length) 31 { 32 //异常处理,wait属于必须要捕获的异常 33 try 34 { 35 this.wait(); 36 } 37 catch(Exception e) 38 { 39 //可以不做任何处理 40 } 41 } 42 //唤醒另一个进程 43 this.notify(); 44 45 //讲数据以压栈的方式存入货架 46 data[cnt] = ch; 47 48 //有效个数自增 49 cnt++; 50 51 System.out.printf("第%d个产品已经生产好,该产品为%c ",cnt,ch); 52 } 53 54 //消费方法 55 public synchronized char pop() 56 { 57 //定义货物 58 char ch = 0; 59 60 //每一次都要检查是否已经把杯子里的货物消费完 61 //如果消费完了,则进入等待状态,唤醒另一个进程 62 while(cnt == 0) 63 { 64 //wait属于必须要捕获的异常 65 try 66 { 67 this.wait(); 68 } 69 catch(Exception e) 70 { 71 //可以不做任何处理 72 } 73 } 74 75 //唤醒另一个进程 76 this.notify(); 77 78 //把货物消费掉 79 cnt--; 80 ch = data[cnt]; 81 System.out.printf("正在消费掉第%d个货物,该货物为%c ",cnt+1,ch); 82 return ch; 83 } 84 } 85 86 //生产类 87 class producer implements Runnable 88 { 89 //定义父类的引用,私有的原因是不想任意修改父类引用的指向 90 public synstack ss = null; 91 92 //构造方法,通过多态实现指向的不同,从而达到调用内部方法的作用 93 public producer(synstack ss) 94 { 95 this.ss = ss; 96 } 97 98 //重写run方法,以用来实现输入 99 public void run() 100 { 101 char ch = 0; 102 for(int i=0; i<26; i++) 103 { 104 ch =(char) ('a' + i); 105 ss.push(ch); 106 /* 107 * 我当时代码写到这一步遇到的问题 108 * 目前问题是无法调用push方法,只能通过多态的方式解决 109 */ 110 111 } 112 } 113 } 114 115 //消费类 116 class consumer implements Runnable 117 { 118 //定义父类的引用,私有的原因是不想任意修改父类引用的指向 119 private synstack ss = null; 120 121 //构造方法,通过多态的实现父类引用指向的不同,从而达到调用内部方法的作用 122 public consumer(synstack ss) 123 { 124 //this出现在构造方法中时表示正在构造的对象 125 this.ss = ss; 126 } 127 //重写run方法,实现输出 128 public void run() 129 { 130 //刻意得减慢消费的速度 131 for(int i=0; i<26; i++) 132 { 133 //sleep属于必须要捕获的异常 134 try 135 { 136 Thread.sleep(1000); 137 } 138 catch(Exception e) 139 { 140 141 } 142 143 //开始调用消费 144 ss.pop(); 145 } 146 147 148 } 149 } 150 151 152 public class Pc 153 { 154 public static void main(String[] args) 155 { 156 //构造出杯子对象 157 synstack ss = new synstack(); 158 159 //构建出生产对象 160 producer p = new producer(ss); 161 162 //构建出消费对象 163 consumer c = new consumer(ss); 164 165 //创建线程,第二种方式 166 Thread t1 = new Thread (p); 167 Thread t2 = new Thread (c); 168 169 //开启线程 170 t1.start(); 171 t2.start(); 172 173 } 174 }