黑马程序员——总结下线程学习中的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:被唤醒的线程继续执行睡眠之前的下一条语句


其实针对线程还有几个问题一时没有搞明白,连怎么描述问题都不甚清楚,就是觉得哪里可能有点怪怪的

0 0
原创粉丝点击