生产者消费者模型(多个生产者和多个消费者)JDK1.5 (Lock&Condition)实现版
2016-04-08 10:31
507 查看
生产者消费者模型(多个生产者和多个消费者)JDK1.5 (Lock&Condition)实现版
场景描述
多线程开发中很经典的一个案例就是生产者消费者模型,它们共享资源,但是对资源的操作方式并不同。因此它们需要协调资源,否则就会出现线程安全问题。尤其当时多个生产者和多个消费者时比较麻烦。本文以JDK1.5并发工具包下的Lock和Condition来实现多生产者多消费者模型。代码展示
Resource Code/** * 生产者和消费者共享的资源Resource对象 * @author xuyi3 * @2016年4月7日 @下午2:01:21 * @Resource * @功能说明:<br> * @春风十里不如你 * @备注:使用Lock 和 Condition实现多生产者和多消费者模型 */ public class Resource { /** 资源名称 */ private String name; /** 资源标识符 */ private boolean flag = false; // 区分产品的计数器 private int count = 0; // 定义一个锁 Lock lock = new ReentrantLock(); // 生产者的监视器 Condition conditionProduce = lock.newCondition(); // 消费者的监视器 Condition conditionConsumer = lock.newCondition(); /** * 生产产品方法 * @param threadName */ public void produce(String threadName) { try { // 其实用tryLock方法更严谨些 lock.lock(); while (isFlag()) {// 如果已经存在数据,生产者就等待消费者消费之后再生产。注意多生产者时这里要使用while循环判断。 // 线程等待 conditionProduce.await(); } setName("产品" + (++count)); System.out.println(threadName + "生产者生产--->" + getName()); setFlag(true); conditionConsumer.signal(); } catch (Exception e) { e.printStackTrace(); } finally { // finally代码块通常都是存放资源释放操作的代码 // 不管执行过程发生什么情况都要释放锁资源,否则就会无限期等待下去了。导致程序崩溃 lock.unlock(); } } /** * 消费产品方法 * @param threadName */ public void consumer(String threadName) { try { // 其实用tryLock方法更严谨些 lock.lock(); while (!isFlag()) {// 如果没有数据消费者就等待生产者生产之后再消费,多消费者时这里要使用while循环判断。 conditionConsumer.await(); } System.out.println(threadName + "消费者消费=====》" + getName()); setFlag(false);// 标识已经消费了 conditionProduce.signal(); } catch (Exception e) { e.printStackTrace(); } finally { // finally代码块通常都是存放资源释放操作的代码 // 不管执行过程发生什么情况都要释放锁资源,否则就会无限期等待下去了。导致程序崩溃 lock.unlock(); } } }
ProductThread Code
/** * 生产者对象 * @author xuyi3 * @2016年4月7日 @下午1:38:16 * @ProductThread * @功能说明:生产产品<br> * @春风十里不如你 * @备注 */ public class ProductThread implements Runnable { // 共享资源对象 private Resource resource; public ProductThread(Resource resource) { this.resource = resource; } @Override public void run() { // 备注:比较优雅的多线程代码,在run()方法体内尽量出现较少的代码,不推荐把同步代码和一些复杂的逻辑放在run()方法体内。 // 因为如果把所有同步代码都放在run()方法体内写的话,非常不好的维护并且代码结构不够清晰。 while (true) { // 生产者生产产品 resource.produce(Thread.currentThread().getName()); } } }
ConsumerThread Code
/** * 消费者对象 * @author xuyi3 * @2016年4月7日 @下午2:07:22 * @ConsumerThread * @功能说明:<br> * @春风十里不如你 * @备注 */ public class ConsumerThread implements Runnable { // 共享资源Resource对象 private Resource resource; public ConsumerThread(Resource resource) { this.resource = resource; } @Override public void run() { // 备注:比较优雅的多线程代码,在run()方法体内尽量出现较少的代码,不推荐把同步代码和一些复杂的逻辑放在run()方法体内。 // 因为如果把所有同步代码都放在run()方法体内写的话,非常不好的维护并且代码结构不够清晰。 while (true) { // 消费者消费产品 resource.consumer(Thread.currentThread().getName()); } } }
AppMain Code
public class AppMain { public static void main(String[] args) { // 共享资源对象 Resource resource = new Resource(); // 创建生产者对象 ProductThread productThread = new ProductThread(resource); // 创建消费者对象 ConsumerThread consumerThread = new ConsumerThread(resource); // 启动两个线程 new Thread(productThread, "生产者1 ").start(); new Thread(consumerThread, "Consumer1").start(); new Thread(productThread, "生产者2 ").start(); new Thread(consumerThread, "Consumer2").start(); } }
总结说明
多个生产者和多个消费者模型实现的关键在于,资源共享(同步同个对象锁)和资源的标识以及等待唤醒机制wait()和notifyAll()方法。但是每次都需要要判断标识符,因此需要使用while而不能试if。JDK1.5之前使用这种方式处理还不错,但是这里有个明显的问题就是,每次都是唤醒所有的线程,并不是只唤醒我们希望唤醒的线程。这是会降低效率的,尤其是在线程数比较多并发量比较高的时候,就会显得性能并不高。本章使用JDK1.5之后的并发包下的Lock和Condition来高效解决这个问题,关于Lock和Condition的介绍可以参考java doc或Java 理论与实践: JDK 5.0 中更灵活、更具可伸缩性的锁定机制相关文章推荐
- Ubuntu 安装 JDK 问题
- 用vbscript实现启用 Caps Lock (大写)键
- C#中lock死锁实例教程
- 解析使用C# lock同时访问共享数据
- [Oracle] 浅谈Lock与Latch
- mysql下普通用户备份数据库时无lock tables权限的解决方法
- jdk与jre的区别 很形象,很清晰,通俗易懂
- jdk中String类设计成final的原由
- win7下安装 JDK 基本流程
- jdk环境变量配置
- win2003 jsp运行环境架设心得(jdk+tomcat)
- windows linux jdk安装配置方法
- Java编程之jdk1.4,jdk1.5和jdk1.6的区别分析(经典)
- 详解JDK 5 Annotation 注解之@Target的用法介绍
- C#中的lock、Monitor、Mutex学习笔记
- 简单记录Cent OS服务器配置JDK+Tomcat+MySQL
- C#中lock用法详解
- Android开发的IDE、ADT、SDK、JDK、NDK等名词解释
- Java4Android开发教程(一)JDK安装与配置
- Python多线程同步Lock、RLock、Semaphore、Event实例