生产者与消费者问题:
第一步:把架子搭起来
package com.zhj.www;public class ProceduerConsumer {public static void main(String[] args) {}}//馒头实体class wotou{int id;wotou(int id) {this.id = id;}public String toString() {return "wotou : "+id;}}//馒头栈class syncStack{int index = 0;wotou[] arrWT= new wotou[6];//这个容器只能装6个馒头syncStack(int index) {this.index = index;}//往里仍馒头,之所以使用synchronized关键字,是因为防止多个人同时往里扔,public synchronized void push(wotou wt) {arrWT[index] = wt; /*这两行不能分开index++;*/}//从里面取馒头,拿最上面的那一个public synchronized wotou pop() {index--;return arrWT[index];}}/*多个生产者,也就是多个线程同时在执行*///生产者,用于对馒头栈的引用,他需要知道生产完馒头,需要往哪个筐里仍馒头class proceduer implements Runnable{syncStack ss= null;proceduer(syncStack ss) {this.ss = ss;}/*run方法对应着生产过程*/public void run() {for(int i =0;i<20;i++) {wotou wt = new wotou(i);ss.push(wt);}}}//消费者class consumer implements Runnable{syncStack ss= null;consumer(syncStack ss) {this.ss = ss;}public void run() {for(int i =0;i<20;i++) {wotou wotou =ss.pop();System.out.println(wotou);}}}
第二步:
需要考虑当馒头筐满了怎么办?马上就会报错?在push方法里考虑,让这个线程休息一下;
wait方法来源于object;wait的时候这把锁也就不属于我了。但是sleep的时候我仍然抓住这把锁。
package com.zhj.www;import java.io.IOException;public class ProceduerConsumer {public static void main(String[] args) {syncStack ss = new syncStack();proceduer proceduer = new proceduer(ss);consumer consumer = new consumer(ss);new Thread(proceduer).start();new Thread(consumer).start();}}//馒头实体class wotou{int id;wotou(int id) {this.id = id;}public String toString() {return "wotou : "+id;}}//馒头栈class syncStack{int index = 0;wotou[] arrWT= new wotou[6];//这个容器只能装6个馒头//往里仍馒头,之所以使用synchronized关键字,是因为防止多个人同时往里扔,public synchronized void push(wotou wt) {if(index == arrWT.length){try {this.wait();//当前对象正在执行push方法需要wait}catch (InterruptedException e) {e.printStackTrace();}}this.notify();//哪个线程在等待就唤醒哪个线程arrWT[index] = wt; /*这两行不能分开*/index++;}//从里面取馒头,拿最上面的那一个public synchronized wotou pop() {if(index == 0) {try {this.wait();}catch (InterruptedException e) {e.printStackTrace();}}this.notify();//object类里的方法,唤醒一个;index--;return arrWT[index];}}/*多个生产者,也就是多个线程同时在执行*///生产者,用于对馒头栈的引用,他需要知道生产完馒头,需要往哪个筐里仍馒头class proceduer implements Runnable{syncStack ss= null;proceduer(syncStack ss) {this.ss = ss;}/*run方法对应着生产过程*/public void run() {for(int i =0;i<20;i++) {wotou wt = new wotou(i);ss.push(wt);System.out.println("生产了:"+wt);try {Thread.sleep(1000);} catch (InterruptedException e) {e.printStackTrace();}}}}//消费者class consumer implements Runnable{syncStack ss= null;consumer(syncStack ss) {this.ss = ss;}public void run() {for(int i =0;i<20;i++) {wotou wotou =ss.pop();System.out.println("消费了:"+wotou);try {Thread.sleep(1000);} catch (InterruptedException e) {e.printStackTrace();}}}}
运行过程:
可以发现生产一个馒头,就消耗一个馒头。
完善之后的栗子:
package com.zhj.www;import java.io.IOException;public class ProceduerConsumer {public static void main(String[] args) {syncStack ss = new syncStack();proceduer proceduer = new proceduer(ss);consumer consumer = new consumer(ss);new Thread(proceduer).start();new Thread(consumer).start();}}//馒头实体class wotou{int id;wotou(int id) {this.id = id;}public String toString() {return "wotou : "+id;}}//馒头栈class syncStack{int index = 0;wotou[] arrWT= new wotou[6];//这个容器只能装6个馒头//往里仍馒头,之所以使用synchronized关键字,是因为防止多个人同时往里扔,public synchronized void push(wotou wt) {while(index == arrWT.length){try {this.wait();//当前对象正在执行push方法需要wait}catch (InterruptedException e) {e.printStackTrace();}}this.notify();//哪个线程在等待就唤醒哪个线程arrWT[index] = wt; /*这两行不能分开*/index++;}//从里面取馒头,拿最上面的那一个public synchronized wotou pop() {while(index == 0) {try {this.wait();}catch (InterruptedException e) {e.printStackTrace();}}this.notify();//object类里的方法,唤醒一个;index--;return arrWT[index];}}/*多个生产者,也就是多个线程同时在执行*///生产者,用于对馒头栈的引用,他需要知道生产完馒头,需要往哪个筐里仍馒头class proceduer implements Runnable{syncStack ss= null;proceduer(syncStack ss) {this.ss = ss;}/*run方法对应着生产过程*/public void run() {for(int i =0;i<20;i++) {wotou wt = new wotou(i);ss.push(wt);System.out.println("生产了:"+wt);try {Thread.sleep((int)(Math.random()*200));} catch (InterruptedException e) {e.printStackTrace();}}}}//消费者class consumer implements Runnable{syncStack ss= null;consumer(syncStack ss) {this.ss = ss;}public void run() {for(int i =0;i<20;i++) {wotou wotou =ss.pop();System.out.println("消费了:"+wotou);try {Thread.sleep((int)(Math.random()*1000));} catch (InterruptedException e) {e.printStackTrace();}}}}
运行之后。