黑马程序员——总结下线程学习中的wait(),notify()的用法。
来源:互联网 发布:互联网 大数据 济宁 编辑:程序博客网 时间:2024/05/22 18:22
总结下线程学习中的wait(),notify()的用法。
先介绍下例子程序要实现的功能——一种商品,生产者生产多少出来,消费者就买多少(注意顺序,先生产后消费),就这样。程序很简单,一个商品的实体类,一个消费者的线程类,一个生产者的线程类,加上一个主函数入口;此功能用普通的代码写出来很容易,但如果用线程的话,因为两个线程都start()后,你根本不知道同一时间是哪个线程在访问商品的数量,所以需要用到wait()和notify()方法,先贴代码:
package Thread;public class Main3 {/** * @param args */public static void main(String[] args) {// TODO Auto-generated method stubmodel1 m = new model1();one1 o = new one1(m);two1 t = new two1(m);}}class model1{int value;boolean bValue=false;synchronized void get(){if(!bValue)try{wait();}catch(Exception e){}else{System.out.println("this is get,the value is :" + value);bValue=false;notify();}}synchronized void put(int v){if(bValue)try{wait();}catch(Exception e){}else{this.value = v;System.out.println("this is put,the value is :"+value);bValue=true;notify();}}}class one1 implements Runnable{model1 m;int i=0;one1(model1 m){this.m=m;new Thread(this,"getT").start();}public void run(){m.get();System.out.println("i:"+i);}}class two1 implements Runnable{model1 m;int i=0;two1(model1 m){this.m=m;new Thread(this,"putT").start();}public void run(){m.put(i);System.out.println("j:"+i);}}
以上是我一开始敲的错误代码,运行结果为:
this is put,the value is :0this is get,the value is :0this is put,the value is :1this is get,the value is :1this is put,the value is :3this is get,the value is :3this is put,the value is :5this is get,the value is :5this is put,the value is :7this is get,the value is :7this is put,the value is :9
我明明两个线程的run()方法都循环了10次,结果应该为20次才对,为什么呢?问题就在get()和put()方法里面的else{}语句上,把这两个else{}去到结果就对了:
this is put,the value is :0this is get,the value is :0this is put,the value is :1this is get,the value is :1this is put,the value is :2this is get,the value is :2this is put,the value is :3this is get,the value is :3this is put,the value is :4this is get,the value is :4this is put,the value is :5this is get,the value is :5this is put,the value is :6this is get,the value is :6this is put,the value is :7this is get,the value is :7this is put,the value is :8this is get,the value is :8this is put,the value is :9this is get,the value is :9
我是按照书上的例子简化来敲的,省略的都是些输出的语句,else{}语句是我手贱加上去的,一直以为不是这里错了,后面是在没办法了才删掉试试,怎么知道就对了,这也让我对wait(),notify()两个方法有更多的了解,分享一下:wait()方法是使运行状态的线程睡眠,换言之只要运行到wait()方法线程就不往下运行了,哪怕下面还有语句;notify()方法是唤醒睡眠的线程,唤醒后,线程便继续运行睡眠之前还没运行完的语句。明白后来看程序,首先,商品类中有个bValue变量,用来控制现在应该是哪个线程进入商品实体操作数量value的,在主函数新建了消费者线程和生产者线程然后都start(),两个线程同时(可能)进入商品类中,消费者线程进入get()方法,生产者线程进入put()方法,因为bValue初始为false,消费者线程执行wait(),生产者线程执行else{}里面的语句先赋值然后打印一句话,然后把bValue的值改为true,最后才调用notify()方法唤醒消费者线程,这里要注意生产者线程执行完后又开始第二次的循环,再次进入put()方法,因为bValue已经是true了,所以生产者线程wait()睡眠,同时,是同时!消费者线程被唤醒,应该要继续执行语句,但因为语句都被放在else{}里面,所以下一条语句就是跳出此次循环,进入下一次循环,又因为bValue为true,所以执行第二次循环的else{}里面的内容——打印,赋值,唤醒,其实问题已经出来了,线程跳过了一次循环输出语句在第二次循环才输出语句,所以就会出现以上错误的结果,但把else{}去掉后,无论此线程是否wait(),下次被唤醒的时候都会先输出一条语句然后再进行下一次循环,这才是正确的答案。
总结:
1:优先级相同?的线程同时运行(同时指的是下一秒谁在试用CPU不可预知)
2:被唤醒的线程继续执行睡眠之前的下一条语句
其实针对线程还有几个问题一时没有搞明白,连怎么描述问题都不甚清楚,就是觉得哪里可能有点怪怪的
- 黑马程序员——总结下线程学习中的wait(),notify()的用法。
- 黑马程序员——Java多线程—线程同步—wait、notify、notifyAll
- 线程中的wait,notify
- java 线程wait()与notify()的用法
- 多线程总结(五)线程间的通信——wait及notify方法
- 线程间的通信——wait()/notify()
- 线程间的通信——wait及notify方法
- java多线程中的synchronized和wait/notify用法总结
- 黑马程序员:synchronized和wait()、notify()的关系 (一)
- 黑马程序员:synchronized和wait()、notify()的关系 (二)
- 线程间通信——wait notify
- 浅谈一下线程中synchronized块、wait,notify的用法
- 深入线程的wait()/notify()
- 深入线程的wait()/notify()
- 深入线程的wait()/notify()
- 深入线程的wait()/notify()
- 深入线程的wait()/notify()
- 深入线程的wait()/notify()
- SAX、 StAX、 DOM(dom4j优于jdom)处理XML
- c++智能指针使用笔记
- DB2 类似ORACLE的DBLINK解决方法 [DB2数据联邦技术]
- windows工具mstsc远程桌面连接, 方便的在两台电脑间互相拷贝文件
- Apache开启伪静态
- 黑马程序员——总结下线程学习中的wait(),notify()的用法。
- Hibernate3 注解介绍
- Centos使php5.5.4 开机自动启动
- U盘安装ubuntu12.10-iso
- 大端法、小端法、网络字节序
- IBM服务器DSA(动态系统诊断)
- MySQL下载与安装5.6.10.1安装图解
- 软件无线电模块一览
- HDU 4284 Travel / 状态压缩DP