网站设计费用一览表,做网站需要了解,宁波哪家建网站好,wordpress添加分类目录关键词多线程环境中#xff0c;通过队列可以很容易实现数据共享#xff0c;比如经典的“生产者”和“消费者”模型中#xff0c;通过队列可以很便利地实现两者之间的数据共享。 假设我们有若干生产者线程#xff0c;另外又有若干个消费者线程。如果生产者线程需要把准备好的数据共…多线程环境中通过队列可以很容易实现数据共享比如经典的“生产者”和“消费者”模型中通过队列可以很便利地实现两者之间的数据共享。 假设我们有若干生产者线程另外又有若干个消费者线程。如果生产者线程需要把准备好的数据共享给消费者线程利用队列的方式来传递数据就可以很方便地解决他们之间的数据共享问题。但如果生产者和消费者在某个时间段内万一发生数据处理速度不匹配的情况呢理想情况下如果生产者产出数据的速度大于消费者消费的速度并且当生产出来的数据累积到一定程度的时候那么生产者必须暂停等待一下阻塞生产者线程以便等待消费者线程把累积的数据处理完毕反之亦然。 然而在concurrent包发布以前在多线程环境下我们每个程序员都必须去自己控制这些细节尤其还要兼顾效率和线程安全而这会给我们的程序带来不小的复杂度。好在此时强大的concurrent包横空出世了而他也给我们带来了强大的BlockingQueue。在多线程领域所谓阻塞在某些情况下会挂起线程即阻塞一旦条件满足被挂起的线程又会自动被唤醒 BlockingQueue的两个常见阻塞场景1、当队列中没有数据的情况下消费者端的所有线程都会被自动阻塞挂起直到有数据放入队列。2、当队列中填满数据的情况下生产者端的所有线程都会被自动阻塞挂起直到队列中有空闲的位置线程被自动唤醒。 这也是我们在多线程环境下为什么需要BlockingQueue的原因。作为BlockingQueue的使用者我们再也不需要关心什么时候需要阻塞线程什么时候需要唤醒线程因为这一切BlockingQueue都给你一手包办了。 BlockingQueue成员详细介绍1. ArrayBlockingQueue基于数组的阻塞队列实现在ArrayBlockingQueue内部维护了一个定长数组以便缓存队列中的数据对象这是一个常用的阻塞队列除了一个定长数组外ArrayBlockingQueue内部还保存着两个整形变量分别标识着队列的头部和尾部在数组中的位置。 ArrayBlockingQueue在生产者放入数据和消费者获取数据都是共用同一个锁对象由此也意味着两者无法真正并行运行这点尤其不同于LinkedBlockingQueue按照实现原理来分析ArrayBlockingQueue完全可以采用分离锁从而实现生产者和消费者操作的完全并行运行。Doug Lea之所以没这样去做也许是因为ArrayBlockingQueue的数据写入和获取操作已经足够轻巧以至于引入独立的锁机制除了给代码带来额外的复杂性外其在性能上完全占不到任何便宜。 ArrayBlockingQueue和LinkedBlockingQueue间还有一个明显的不同之处在于前者在插入或删除元素时不会产生或销毁任何额外的对象实例而后者则会生成一个额外的Node对象。这在长时间内需要高效并发地处理大批量数据的系统中其对于GC的影响还是存在一定的区别。而在创建ArrayBlockingQueue时我们还可以控制对象的内部锁是否采用公平锁默认采用非公平锁。 2. LinkedBlockingQueue基于链表的阻塞队列同ArrayListBlockingQueue类似其内部也维持着一个数据缓冲队列该队列由一个链表构成当生产者往队列中放入一个数据时队列会从生产者手中获取数据并缓存在队列内部而生产者立即返回只有当队列缓冲区达到最大值缓存容量时LinkedBlockingQueue可以通过构造函数指定该值才会阻塞生产者队列直到消费者从队列中消费掉一份数据生产者线程会被唤醒反之对于消费者这端的处理也基于同样的原理。而LinkedBlockingQueue之所以能够高效的处理并发数据还因为其对于生产者端和消费者端分别采用了独立的锁来控制数据同步这也意味着在高并发的情况下生产者和消费者可以并行地操作队列中的数据以此来提高整个队列的并发性能。 作为开发者我们需要注意的是如果构造一个LinkedBlockingQueue对象而没有指定其容量大小LinkedBlockingQueue会默认一个类似无限大小的容量Integer.MAX_VALUE这样的话如果生产者的速度一旦大于消费者的速度也许还没有等到队列满阻塞产生系统内存就有可能已被消耗殆尽了。 ArrayBlockingQueue和LinkedBlockingQueue是两个最普通也是最常用的阻塞队列一般情况下在处理多线程间的生产者消费者问题使用这两个类足以。 ArrayBlockingQueue和LinkedBlockingQueue的区别1.队列中锁的实现不同ArrayBlockingQueue实现的队列中的锁是没有分离的即生产和消费用的是同一个锁LinkedBlockingQueue实现的队列中的锁是分离的即生产用的是putLock消费用的是takeLock2.在生产或消费时操作不同ArrayBlockingQueue实现的队列中在生产和消费的时候是直接将枚举对象插入或移除的LinkedBlockingQueue实现的队列中在生产和消费的时候需要把枚举对象转换为NodeE进行插入或移除会影响性能 3.队列大小初始化方式不同ArrayBlockingQueue实现的队列中必须指定队列的大小LinkedBlockingQueue实现的队列中可以不指定队列的大小但是默认是Integer.MAX_VALUE 注意:1. 在使用LinkedBlockingQueue时若用默认大小且当生产速度大于消费速度时候有可能会内存溢出2. 在使用ArrayBlockingQueue和LinkedBlockingQueue分别对10,00000个简单字符做入队操作时LinkedBlockingQueue的消耗是ArrayBlockingQueue消耗的10倍左右即LinkedBlockingQueue消耗在1500毫秒左右而ArrayBlockingQueue只需150毫秒左右。