欢迎来到天天文库
浏览记录
ID:34723850
大小:407.39 KB
页数:16页
时间:2019-03-10
《java简单的挂起以及文字说明》由会员上传分享,免费在线阅读,更多相关内容在工程资料-天天文库。
1、JAVA生产者消费者背景 进入正题之前先说点故事。从最开始学java的那里开始:我是从08年下半年开始学Java,在《我的六年程序之路》中提到了一些。当时比较简单,每天看尚学堂的视频(对于初学者而言看视频好一些。),然后写代码。比较清楚的记得马士兵讲到生产者消费者模型的时候还大谈特谈要是掌握了这个工资可以+1000(现在回忆起有点像历史一样,多少有些伤感)。那时候已经过年了,我在家的时候把那段代码敲了很多遍,不过基本上是默写下来的,也没有仔细的想过其中的一些细节,不久后我就忘记了其中的写法。这里又衍生出一个学习方法的问题。我在学习上一直有一个毛病:学习的过程中不会刨根问底
2、,这导致很多问题思考的不透彻,在后面很大程度上影响我整个知识体系的扎实程度,也应了那句话:出来混迟早要还的,在学习技术的过程中就是要一步一个脚印,总有一天会豁然开朗,不知不觉的发现所有知识都串起来了,一件很神奇的事情。在技术学习的过程中还是需要有点钻牛角尖的精神,基本上技术上的大牛都有钻牛角尖的“毛病”。 第二段故事是在2012年,这是正儿八经的使用生产者消费者模型在项目中进行开发,中间也写出了一大堆问题,这个不是写出来的,是慢慢调试出来的。最开始使用wait(),notify(),后来用CountDownLatch。 第三个故事是前几天的事情,这也是我为什么要写这
3、篇文章的原因。一个同事问我代码的问题,他里面就是用到了生产者消费者,当时我整了半天都没整利索,很没面子。后面虽然找出了问题(这个问题我今天也碰到了),就是习惯性的把整个容器(下面代码的Container)锁住,然后发现只要一个线程wait住,所有线程都不动了,因为这个wait住的线程还持有Container的锁没有释放,其他线程也就进不来。我发现自己对于这个模型并没有完全摸透,就在周末的时候好好的把这个模型从头到尾的写了写,当然从中又有一些新的收获。正题 上面说了一大堆故事。下面就开始今天的主题:生产者消费者模型。这里先问两个问题:1、生产者消费者模型旨在解决什么问题。2
4、、在现有的场景下哪里会用到?模型图 从下面图中可以发现生产者和消费者之间用中间类似一个队列一样的东西串起来。这个队列可以想像成一个存放产品的“仓库”,生产者只需要关心这个“仓库”,并不需要关心具体的消费者,对于生产者而言甚至都不知道有这些消费者存在。对于消费者而言他也不需要关心具体的生产者,到底有多少生产者也不是他关心的事情,他只要关心这个“仓库”中还有没有东西。这种模型是一种松耦合模型。这样可以回答我上面提出的第一个问题。这个模16型的产生就是为了复用和解耦。比如常见的消息框架(非常经典的一种生产者消费者模型的使用场景)ActiveMQ。发送端和接收端用Topic进行
5、关联。这个Topic可以理解为我们这里“仓库”的地址,这样就可以实现点对点和广播两种方式进行消息的分发。具体实现 我的代码里只是简单的模拟了这样一个模型的实现。在写的过程中还是碰到一些问题。编程过程中一旦用多线程复杂度就会陡升。所以编码原则是能用单线程解决问题就不要去用多线程。UML类图 图中比较简单的画了生产者和消费者之间的关系,如果看到这里还比较迷惑没有关系,下面会有具体的代码展示。当然最好的方式就是自己从头开始写,这样可以知道一些在看文章中遗漏的一些细节。在学习的过程中往往会有这样的感受:你以为你看懂了,理解了,自己写的时候就发现傻眼了,这也是为什么代码一定要
6、多写,写的过程是即是思考的过程。16逻辑分析 下面我会重点讲两个类的代码,Consumer.java和Producer.java,以及我在写的过程中碰到了些什么问题。现在有点发现用一篇的篇幅有点讲不清楚,代码我会在后面贴出来,我估计在这里贴出来也很少人会去看这个代码。从我自己的经验来看一看到一大坨的代码就傻眼了。Producer.java16Consumer.java16 先回答我上面的两把锁的问题,对于生产者和消费者的唤醒和挂起操作分别用了两个监控器。原因很简单,就像我在生产者消费者模型图里面看到的生产者和消费者均可以是一个或者多个。如果这里用一个对象控制,在多个
7、生产者和多个消费者的时候发现:本来要唤醒生产者会把消费者也唤醒,就会比较混乱。 再看第二个问题是:为什么在三个地方都需要做判满操作?这里看生产者那张图,仔细的看这一段代码,这里的操作并非原子操作。图中标识的1处判满操作后,到了第3处后并不意味着容器还是满的。如果只是在1处作了校验,那么很有可能会出现这样的情况:在2处把消费者唤醒后,等运行到了第3处发现这时候的容器可能已经空了!这样就不需要把生产者进行挂起。而如果没有这段校验逻辑很有可能就会出现生产者和消费者同时挂起的情况,这里可以细细
此文档下载收益归作者所有