java生产消费问题
来源:互联网 发布:ubuntu如何重置系统 编辑:程序博客网 时间:2024/04/30 13:55
编写SynStack类
最基础的想法如下:Consumer类和Producer类实现Runnable接口,run方法中调用push与pop
public class SynStack { private char[] data = new char[6]; private int cnt=0; public void push(char ch){ data[cnt]=ch; cnt++; System.out.println("生产线程,生产第"+cnt+"个产品,此产品是"+ch); } public char pop(){ char ch=data[cnt-1]; System.out.println("消费线程,消费第"+cnt+"个产品,此产品是"+ch); --cnt; return ch; }}
问题:无法控制消费与生产哪个先执行,若消费先执行,data[-1]越界,报错,故必须对满或空加以判断,空则无法消费,满则无法继续生产.
加以改进,完整代码如下
public class SynStack { private char[] data = new char[6]; private int cnt=0; public synchronized void push(char ch){ while(cnt == data.length){ try { this.wait(); } catch (InterruptedException e) { // TODO Auto-generated catch block e.printStackTrace(); } } this.notify(); data[cnt]=ch; cnt++; System.out.println("生产线程,生产第"+cnt+"个产品,此产品是"+ch); } public synchronized char pop(){ while(cnt == 0){ try { this.wait(); } catch (InterruptedException e) { // TODO Auto-generated catch block e.printStackTrace(); } } this.notify(); char ch=data[cnt-1]; System.out.println("消费线程,消费第"+cnt+"个产品,此产品是"+ch); --cnt; return ch; }}
public class Producer implements Runnable{ private SynStack ss =null; public Producer(SynStack ss){ this.ss = ss; } @Override public void run() { // TODO Auto-generated method stub char ch; for(int i=0;i<20;++i){ ch =(char)('a'+i); ss.push(ch); /*try { Thread.sleep(1000); } catch (InterruptedException e) { // TODO Auto-generated catch block e.printStackTrace(); }*/ } }}
public class Consumer implements Runnable{ private SynStack ss = null; public Consumer(SynStack ss){ this.ss = ss; } @Override public void run() { // TODO Auto-generated method stub for(int i=0;i<20;++i){ ss.pop(); } }}
public class Consumer implements Runnable{ private SynStack ss = null; public Consumer(SynStack ss){ this.ss = ss; } @Override public void run() { // TODO Auto-generated method stub for(int i=0;i<20;++i){ ss.pop(); } }}
解释:
- synchronized修饰方法,表示当前线程霸占正在调用该方法的对象(本例中即SynStack的实例ss)。即生产线程执行push时,会先判断ss是否被消费线程霸占,若没有,则生产线程霸占ss,执行push。从而保证了在执行push操作时,不会切到消费线程去执行
- wait与notify:aa.wait()表示将执行aa.wait()的线程阻塞,并释放对aa的锁定。若有T1,T2两个线程,T1由于执行过aa.wait()而阻塞,当T2中执行aa.notify()时,即将T1线程唤醒,转为就绪态
运行结果
生产线程,生产第1个产品,此产品是a生产线程,生产第2个产品,此产品是b生产线程,生产第3个产品,此产品是c生产线程,生产第4个产品,此产品是d生产线程,生产第5个产品,此产品是e生产线程,生产第6个产品,此产品是f消费线程,消费第6个产品,此产品是f生产线程,生产第6个产品,此产品是g消费线程,消费第6个产品,此产品是g生产线程,生产第6个产品,此产品是h消费线程,消费第6个产品,此产品是h生产线程,生产第6个产品,此产品是i消费线程,消费第6个产品,此产品是i生产线程,生产第6个产品,此产品是j消费线程,消费第6个产品,此产品是j生产线程,生产第6个产品,此产品是k消费线程,消费第6个产品,此产品是k生产线程,生产第6个产品,此产品是l消费线程,消费第6个产品,此产品是l生产线程,生产第6个产品,此产品是m消费线程,消费第6个产品,此产品是m生产线程,生产第6个产品,此产品是n消费线程,消费第6个产品,此产品是n生产线程,生产第6个产品,此产品是o消费线程,消费第6个产品,此产品是o生产线程,生产第6个产品,此产品是p消费线程,消费第6个产品,此产品是p生产线程,生产第6个产品,此产品是q消费线程,消费第6个产品,此产品是q生产线程,生产第6个产品,此产品是r消费线程,消费第6个产品,此产品是r生产线程,生产第6个产品,此产品是s消费线程,消费第6个产品,此产品是s生产线程,生产第6个产品,此产品是t消费线程,消费第6个产品,此产品是t消费线程,消费第5个产品,此产品是e消费线程,消费第4个产品,此产品是d消费线程,消费第3个产品,此产品是c消费线程,消费第2个产品,此产品是b消费线程,消费第1个产品,此产品是a
还存在问题吗?
- 代码中生产20次,消费20次,程序可以正常结束。若不匹配,程序会停住,无法正常结束,也不会继续成产与消费。当然,可以将run()中pop与push放在死循环里,不停的生产与消费。
- pop()与push()中对空和满的判断一定要用while吗,换成if判断不行吗?我的主函数中就一个生产者,一个消费者,运行没有问题。若有多个生产者,多个消费者时,必须用while。我用1个生产者,2个消费者测试,提示-1数组越界,详细请看如何在 Java 中正确使用 wait, notify 和 notifyAll
0 0
- java生产消费问题
- Java模拟生产消费问题
- java多线程之生产消费问题
- 【Java】----线程同步:生产-消费问题
- Java 线程同步 生产消费问题
- java信号量解决生产消费问题
- 多线程生产消费问题
- 线程---生产消费问题
- 生产消费问题
- Java多线程的单生产单消费和多生产多消费问题的解决
- JAVA进阶6.8——生产消费问题
- Java并发(八)生产消费问题&虚假唤醒
- Java 多线程间通信 多生产 多消费问题
- 线程 --生产和消费问题
- 生产消费问题整合版
- 多线程之生产消费问题
- 生产消费中的死锁问题
- java线程同步----生产消费
- Java读写.properties文件实例,解决中文乱码问题
- A Bug's Life (分组 并查集)
- HDU2795 Billboard(线段树单点更新,区间最大值)
- JSP中EL表达式的取值
- Android——JNI加载so两种方式
- java生产消费问题
- hbase高性能读取数据
- c++中this指针的用法
- UE4 简易天空盒制作
- 53-套接字选项(SO_REUSEADDR)
- matlab安装后的启动以及权限问题
- 登录密码案例
- 在action中配置@Result(params={"root","{d,message}"})
- JavaSE 学习参考:反射机制(1)