javaee论坛

普通会员

225648

帖子

331

回复

345

积分

楼主
发表于 2019-11-08 13:23:16 | 查看: 571 | 回复: 2

二、使用wait()、notify()、notifyAll()应该要注意的地方 1、wait(),notify(),notifyAll()都不属于Thread类,属于Object基础类,每个对象都有wait(),notify(),notifyAll()的功能,因为每个对象都有锁  2、当需要调用wait(),notify(),notifyAll()的时候,一定都要在synchronized里面,不然会报IllegalMonitorStateException异常,可以这样理解,在synchronized(object){}里面的代码才能获取到对象的锁。 3、while循环里而不是if语句下使用wait,这样,会在线程暂停恢复后都检查wait的条件,并在条件实际上并未改变的情况下处理唤醒通知 4、调用obj.wait()释放了obj的锁,程序就会阻塞在这里,如果后面被notify()或者notifyAll()方法呼唤醒了之后,那么程序会接着调用obj.wait()后面的程序。   5、notify()唤醒等待获取锁资源的单个线程,notifyAll()唤醒等待获取锁资源的所有线程 6、当调用obj.notify/notifyAll后,调用线程依旧持有obj锁,其它线程仍无法获得obj锁,直到调用线程退出synchronized块或者在原有的obj调用wait释放锁,其它的线程才能起来

三、使用wait()、notify()、notifyAll()实现非阻塞式的消费者和生产者packagewait;importjava.util.PriorityQueue;publicclassWaitAndNofityTest{publicstaticfinalintCOUNT=5;//优先队列,消费者在这个队列里面消耗数据,生产者在这个里面生产数据publicPriorityQueue<Integer>queue=newPriorityQueue<Integer>(COUNT);publicstaticvoidmain(String[]args){WaitAndNofityTestwaitAndNofityTest=newWaitAndNofityTest();Cuscus=waitAndNofityTest.newCus();Makemake=waitAndNofityTest.newMake();make.start();cus.start();}//消费者线程类classCusextendsThread{@Overridepublicvoidrun(){System.out.println("Cusqueuesizeis:"+queue.size());eatData();}publicvoideatData(){while(true){synchronized(queue){System.out.println("gotoeatDatamethodsizeis:"+queue.size());while(queue.size()==0){try{System.out.println("Cusstartnotify");queue.notify();System.out.println("Cusstartwait");queue.wait();System.out.println("Cuswaitafter");}catch(InterruptedExceptione){queue.notify();}}queue.poll();System.out.println("CuseatDataaftersizeis:"+queue.size());}}}}//生产者线程类classMakeextendsThread{@Overridepublicvoidrun(){System.out.println("Makequeuesizeis:"+queue.size());addData();}publicvoidaddData(){while(true){synchronized(queue){System.out.println("gotoaddDatamethodsizeis:"+queue.size());while(queue.size()==COUNT){try{System.out.println("Makestartnotify");queue.notify();System.out.println("Makestartwait");queue.wait();System.out.println("Makewaitafter");}catch(InterruptedExceptione){queue.notify();}}queue.offer(5);System.out.println("CusaddDataaftersizeis:"+queue.size());}}}}}

四、部分运行结果CusaddDataaftersizeis:5gotoaddDatamethodsizeis:5MakestartnotifyMakestartwaitCuswaitafterCuseatDataaftersizeis:4gotoeatDatamethodsizeis:4CuseatDataaftersizeis:3gotoeatDatamethodsizeis:3CuseatDataaftersizeis:2gotoeatDatamethodsizeis:2CuseatDataaftersizeis:1gotoeatDatamethodsizeis:1CuseatDataaftersizeis:0gotoeatDatamethodsizeis:0CusstartnotifyCusstartwaitMakewaitafterCusaddDataaftersizeis:1gotoaddDatamethodsizeis:1CusaddDataaftersizeis:2gotoaddDatamethodsizeis:2CusaddDataaftersizeis:3gotoaddDatamethodsizeis:3CusaddDataaftersizeis:4gotoaddDatamethodsizeis:4CusaddDataaftersizeis:5gotoaddDatamethodsizeis:5MakestartnotifyMakestartwaitCuswaitafterCuseatDataaftersizeis:4gotoeatDatamethodsizeis:4CuseatDataaftersizeis:3gotoeatDatamethodsizeis:3CuseatDataaftersizeis:2gotoeatDatamethodsizeis:2CuseatDataaftersizeis:1gotoeatDatamethodsizeis:1CuseatDataaftersizeis:0gotoeatDatamethodsizeis:0CusstartnotifyCusstartwaitMakewaitafterCusaddDataaftersizeis:1gotoaddDatamethodsizeis:1CusaddDataaftersizeis:2gotoaddDatamethodsizeis:2CusaddDataaftersizeis:3gotoaddDatamethodsizeis:3CusaddDataaftersizeis:4gotoaddDatamethodsizeis:4CusaddDataaftersizeis:5gotoaddDatamethodsizeis:5MakestartnotifyMakestartwaitCuswaitafterCuseatDataaftersizeis:4gotoeatDatamethodsizeis:4CuseatDataaftersizeis:3gotoeatDatamethodsizeis:3CuseatDataaftersizeis:2gotoeatDatamethodsizeis:2CuseatDataaftersizeis:1gotoeatDatamethodsiz如果运行了不理解,你可以自己测试然后分析打印的数据,当然你也可以注释掉2个类里面的任意一个notify方法,然后看是什么效果,是不是和自己分析的结果一样,同样你也可以去掉第一类的wait方法试下,看执行notify方法后是synchronized执行完了呼唤其其它线程或则在调用wait方法之后释放锁后是否也会呼唤其线程?

五、用ArrayBlockingQueue实现阻塞式的生产者和消费者

官方API

packagewait;importjava.util.concurrent.ArrayBlockingQueue;publicclassBlockTest{privateintCOUNT=5;privateArrayBlockingQueue<Integer>queue=newArrayBlockingQueue<Integer>(COUNT);publicstaticvoidmain(String[]args){BlockTesttest=newBlockTest();Makemake=test.newMake();Cuscus=test.newCus();make.start();cus.start();}classCusextendsThread{@Overridepublicvoidrun(){eatData();}privatevoideatData(){while(true){try{queue.take();System.out.println("队列取一个元素,队列剩余"+queue.size()+"元素");}catch(InterruptedExceptione){e.printStackTrace();}}}}classMakeextendsThread{@Overridepublicvoidrun(){addData();}privatevoidaddData(){while(true){try{queue.put(5);System.out.println("队列插入一个元素,队列剩余空间:"+(COUNT-queue.size()));}catch(InterruptedExceptione){e.printStackTrace();}}}}}

六、部分运行结果队列取一个元素,队列剩余4元素队列取一个元素,队列剩余3元素队列取一个元素,队列剩余2元素队列取一个元素,队列剩余1元素队列取一个元素,队列剩余0元素队列插入一个元素,队列剩余空间:4队列插入一个元素,队列剩余空间:3队列插入一个元素,队列剩余空间:2队列插入一个元素,队列剩余空间:1队列插入一个元素,队列剩余空间:0队列取一个元素,队列剩余4元素队列取一个元素,队列剩余3元素队列取一个元素,队列剩余2元素队列取一个元素,队列剩余1元素队列取一个元素,队列剩余0元素队列插入一个元素,队列剩余空间:4队列插入一个元素,队列剩余空间:3队列插入一个元素,队列剩余空间:2队列插入一个元素,队列剩余空间:1队列插入一个元素,队列剩余空间:0队列取一个元素,队列剩余4元素队列取一个元素,队列剩余3元素队列取一个元素,队列剩余2元素队列取一个元素,队列剩余1元素队列取一个元素,队列剩余0元素队列插入一个元素,队列剩余空间:4队列插入一个元素,队列剩余空间:3队列插入一个元素,队列剩余空间:2队列插入一个元素,队列剩余空间:1队列插入一个元素,队列剩余空间:0队列取一个元素,队列剩余4元素队列取一个元素,队列剩余3元素队列取一个元素,队列剩余2元素队列取一个元素,队列剩余1元素队列取一个元素,队列剩余0元素队列插入一个元素,队列剩余空间:4队列插入一个元素,队列剩余空间:3队列插入一个元素,队列剩余空间:2队列插入一个元素,队列剩余空间:1队列插入一个元素,队列剩余空间:0队列取一个元素,队列剩余4元素队列取一个元素,队列剩余3元素队列取一个元素,队列剩余2元素队列取一个元素,队列剩余1元素队列取一个元素,队列剩余0元素队列插入一个元素,队列剩余空间:4队列插入一个元素,队列剩余空间:3队列插入一个元素,队列剩余空间:2队列插入一个元素,队列剩余空间:1队列插入一个元素,队列剩余空间:0队列取一个元素,队列剩余4元素队列取一个元素,队列剩余3元素队列取一个元素,队列剩余2元素队列取一个元素,队列剩余1元素队列取一个元素,队列剩余0元素队列插入一个元素,队列剩余空间:4队列插入一个元素,队列剩余空间:3队列插入一个元素,队列剩余空间:2队列插入一个元素,队列剩余空间:1队列插入一个元素,队列剩余空间:0队列取一个元素,队列剩余4元素队列取一个元素,队列剩余3元素队列取一个元素,队列剩余2元素队列取一个元素,队列剩余1元素队列取一个元素,队列剩余0元素队列插入一个元素,队列剩余空间:4队列插入一个元素,队列剩余空间:3队列插入一个元素,队列剩余空间:2队列插入一个元素,队列剩余空间:1队列插入一个元素,队列剩余空间:0队列取一个元素,队列剩余4元素


普通会员

0

帖子

279

回复

293

积分
沙发
发表于 2019-12-22 03:09:16

很好

普通会员

2

帖子

306

回复

318

积分
板凳
发表于 2024-01-15 14:14:44

楼主听话,快到碗里来!

您需要登录后才可以回帖 登录 | 立即注册

触屏版| 电脑版

技术支持 历史网 V2.0 © 2016-2017