java多线程交互 经典实例__生产者与消费者模型
2012-06-13 16:39
453 查看
由于在项目中的一些教训,最近回顾了一下多线程,写了下面这样一个简单的实例。
多线程的重点应当在于,线程的交互和锁,锁用来保护数据的原子性,线程的交互用于更灵活的线程通信。
测试线程的交互性,线程间交互实现以下细节:
* 生产者—消费—仓库 模型
* 测试线程的交互性
* 主要实现:
* 第一:生产者 生产的消费品 存放到仓库中,当仓库满时,生产者停止生产
* 第二:消费者 到仓库中 使用消费品,当仓库没有消费品时,停止消费
* 第三:生产者 在仓库满停止生产后 通知消费者去消费
* 第四:消费者 在仓库没有消费品时 通知生产者生产
* 第五:生产者 不可以消亡除非没有消费者进行再消费 消费者可以消亡
直接上代码了啊:
在上述实例中 我们使用了 连个对象的锁,即stb对象的锁 和 lock对象的锁,stb对象的锁 用来保护数据的完整性,lock对象的锁用于 生产者线程与消费者线程之间的服务,
在上述有两个地方需要注意:
第一:为什么要将 生产者线程 设置为守护线程 也就是后台线程,如果不设置成这样,又会产生什么样的结果。
第二:在消费者的同步代码块中 为什么有一个else 如果去掉else ,将if中的i--也去掉 ,会有什么问题,有什么原因导致呢?(如果你自己写你考虑到了吗?考虑到是什么原因了吗?)
代码应该不算很绕,关键是线程之间交互的一些细节需要注意,下面我们来看看以上两个问题:
第一个问题:
众多消费者 在将仓库中的消费品用完时 通知生产者进行生产 ,也就是说 只要有消费者存在就有可能将仓库中的消费品消费完,所以生产者线程 需要一直存在,直到没有消费者存在时,才能消亡,
所以生成者线程 完全可以看做为一个服务程序,后台线程的生命周期 到用户线程全部消亡时 才会被销毁。
如果不将生产者作为一个后台线程,由于lock对象 一直在处于等待状态 ,所以全部的消费者消亡后 生产者还会存在,如果不设置生产者为后台线程,那么它会一直存在,占用着系统资源。当然 如果这个服务能确保永远的进行服务,可以不设置成后台线程。
第二个问题:
首先启动生产者,生产者处于等待被唤醒状态,然后启动一千个消费者线程,当这些线程进行消费时,必须首先获得stb对象的锁才能够进行消费,当第i-1个线程消费掉最后一个消费品时(即stb对象的curr=0时),
第i个消费者线程获得了stb对象的锁后,判断没有消费品了,通知生产者,然后调用wait方法,线程调用wait方法时,会放弃当前对象的锁,放弃对象的锁意味着 其他等待该对象锁的线程 争先获得该锁,由于没有消费品,有一些消费者即使获得了锁
也会因没有物品而通知消费者进入等待状态,即在生产者获得stb对象的锁之前,所有获stb对象锁的消费者线程,都会处于等待状态,比如说有200个线程,处于等待状态,然后生产者获得线程,进行生产了max_size(100)个消费品,然后
notifyAll所有等待stb对象的线程,由于等待线程执行的位置为i--;处,所以如果去掉else这个地方,如果那200个消费线程获得了stb对象的锁,并且执行stb.custom()方法,没有再次调用stb.haveThings()进行判断,那么就会出现消费品为负数的
的情况,即使调用了haveThings方法,如果没有消费品时,还会在重复stb.wait()方法,所以此处为else存在的原因,也就一句话,当所有的消费者线程 阻塞在了 消费方法之前时,当他们再次获得锁时,会造成数据破坏的可能。
知识关键点:
当调用对象的wait方法时,会放弃对象的锁!
线程调用对象的 wait() notify() notifyAll() 方法时,必须在对象的同步环境中,即线程必须获得该对象的锁
多线程的重点应当在于,线程的交互和锁,锁用来保护数据的原子性,线程的交互用于更灵活的线程通信。
测试线程的交互性,线程间交互实现以下细节:
* 生产者—消费—仓库 模型
* 测试线程的交互性
* 主要实现:
* 第一:生产者 生产的消费品 存放到仓库中,当仓库满时,生产者停止生产
* 第二:消费者 到仓库中 使用消费品,当仓库没有消费品时,停止消费
* 第三:生产者 在仓库满停止生产后 通知消费者去消费
* 第四:消费者 在仓库没有消费品时 通知生产者生产
* 第五:生产者 不可以消亡除非没有消费者进行再消费 消费者可以消亡
直接上代码了啊:
在上述实例中 我们使用了 连个对象的锁,即stb对象的锁 和 lock对象的锁,stb对象的锁 用来保护数据的完整性,lock对象的锁用于 生产者线程与消费者线程之间的服务,
在上述有两个地方需要注意:
第一:为什么要将 生产者线程 设置为守护线程 也就是后台线程,如果不设置成这样,又会产生什么样的结果。
第二:在消费者的同步代码块中 为什么有一个else 如果去掉else ,将if中的i--也去掉 ,会有什么问题,有什么原因导致呢?(如果你自己写你考虑到了吗?考虑到是什么原因了吗?)
代码应该不算很绕,关键是线程之间交互的一些细节需要注意,下面我们来看看以上两个问题:
第一个问题:
众多消费者 在将仓库中的消费品用完时 通知生产者进行生产 ,也就是说 只要有消费者存在就有可能将仓库中的消费品消费完,所以生产者线程 需要一直存在,直到没有消费者存在时,才能消亡,
所以生成者线程 完全可以看做为一个服务程序,后台线程的生命周期 到用户线程全部消亡时 才会被销毁。
如果不将生产者作为一个后台线程,由于lock对象 一直在处于等待状态 ,所以全部的消费者消亡后 生产者还会存在,如果不设置生产者为后台线程,那么它会一直存在,占用着系统资源。当然 如果这个服务能确保永远的进行服务,可以不设置成后台线程。
第二个问题:
首先启动生产者,生产者处于等待被唤醒状态,然后启动一千个消费者线程,当这些线程进行消费时,必须首先获得stb对象的锁才能够进行消费,当第i-1个线程消费掉最后一个消费品时(即stb对象的curr=0时),
第i个消费者线程获得了stb对象的锁后,判断没有消费品了,通知生产者,然后调用wait方法,线程调用wait方法时,会放弃当前对象的锁,放弃对象的锁意味着 其他等待该对象锁的线程 争先获得该锁,由于没有消费品,有一些消费者即使获得了锁
也会因没有物品而通知消费者进入等待状态,即在生产者获得stb对象的锁之前,所有获stb对象锁的消费者线程,都会处于等待状态,比如说有200个线程,处于等待状态,然后生产者获得线程,进行生产了max_size(100)个消费品,然后
notifyAll所有等待stb对象的线程,由于等待线程执行的位置为i--;处,所以如果去掉else这个地方,如果那200个消费线程获得了stb对象的锁,并且执行stb.custom()方法,没有再次调用stb.haveThings()进行判断,那么就会出现消费品为负数的
的情况,即使调用了haveThings方法,如果没有消费品时,还会在重复stb.wait()方法,所以此处为else存在的原因,也就一句话,当所有的消费者线程 阻塞在了 消费方法之前时,当他们再次获得锁时,会造成数据破坏的可能。
知识关键点:
当调用对象的wait方法时,会放弃对象的锁!
线程调用对象的 wait() notify() notifyAll() 方法时,必须在对象的同步环境中,即线程必须获得该对象的锁
相关文章推荐
- java 多线程之 wait(),notify(),notifyAll()以及经典的生产者消费者模型
- 经典多线程Java实例 生产者与消费者
- java 多线程之 wait(),notify(),notifyAll()以及经典的生产者消费者模型
- JAVA多线程之——经典面试消费者与生产者
- Java多线程-并发协作(生产者消费者模型)
- 【Python之旅】第六篇(五):生产者消费者模型实现多线程异步交互
- 经典多线程实例:生产者消费者问题
- java多线程之生产者消费者经典问题
- Java多线程中的生产者消费者模型
- JAVA-多线程机制中关于生产者消费者模型
- C# Thread 多线程 Monitor 锁 Producer And Consumer 生产者和消费者 经典模型
- java多线程之生产者和消费者经典问题案例
- JAVA多线程之——经典面试消费者与生产者
- java: 线程间通信经典模型“生产者-消费者”模型的实现
- java多线程实现生产者与消费者---经典问题
- Java多线程学习之 BlockingQueue实现生产者和消费者模型
- Java多线程15:Queue、BlockingQueue以及利用BlockingQueue实现生产者/消费者模型
- Java多线程生产者消费者实例
- Java多线程系列-Queue、BlockingQueue以及利用BlockingQueue实现生产者/消费者模型
- java多线程之生产者消费者经典问题