Java阻塞队列BlockingQueue

本文介绍了Java中阻塞队列的基本概念与应用场景,详细解释了核心方法如offer、put、poll、take及drainTo的功能与使用场景,并对常见阻塞队列如ArrayBlockingQueue、LinkedBlockingQueue、DelayQueue、SynchronousQueue和PriorityBlockingQueue的特点进行了对比。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

阻塞队列,用于并发环境下共享资源的处理:

1.当队列里没有数据时,消费者端的所有线程都会阻塞,直到有数据放入队列;
2.当队列填满时,生产者端的所有线程会阻塞,直到有空位置,被自动唤醒;

核心方法:

1.放入数据

       (1)offer(anObject):表示如果可能的话,将anObject加到BlockingQueue里,即如果BlockingQueue可以容纳,则返回true,否则返回false.(本方法不阻塞当前执行方法的线程);       

      (2)offer(E o, long timeout, TimeUnit unit):可以设定等待的时间,如果在指定的时间内,还不能往队列中加入BlockingQueue,则返回失败。

    (3)put(anObject):把anObject加到BlockingQueue里,如果BlockQueue没有空间,则调用此方法的线程被阻断直到BlockingQueue里面有空间再继续.

2. 获取数据

    (1)poll(time):取走BlockingQueue里排在首位的对象,若不能立即取出,则可以等time参数规定的时间,取不到时返回null;

    (2)poll(long timeout, TimeUnit unit):从BlockingQueue取出一个队首的对象,如果在指定时间内,队列一旦有数据可取,则立即返回队列中的数据。否则直到时间超时还没有数据可取,返回失败。

    (3)take():取走BlockingQueue里排在首位的对象,若BlockingQueue为空,阻断进入等待状态直到BlockingQueue有新的数据被加入; 

    (4)drainTo():一次性从BlockingQueue获取所有可用的数据对象(还可以指定获取数据的个数),通过该方法,可以提升获取数据效率;不需要多次分批加锁或释放锁。

常见的BlockingQueue:

1. ArrayBlockingQueue
  1. publicclassArrayBlockingQueue<E>extendsAbstractQueue<E>
  2. implementsBlockingQueue<E>, java.io.Serializable{
    基于数组的阻塞队列,内部维护了一个定长数组,用来缓存队列中的数据对象;生产者放入数据和消费者获取数据使用的同一个锁对象,在创建实例时还可以控制对象内部是否采用公平锁(先来先得到锁),默认采用非公平锁(随机分配锁).
    new ArrayBlockingQueue(数组长度,是否采用公平锁)
     new  ArrayBlockingQueue(数组长度),默认使用非公平锁
2. LinkedBlockingQueue
  1. publicclassLinkedBlockingDeque<E>
  2. extendsAbstractQueue<E>
  3. implementsBlockingDeque<E>, java.io.Serializable{
    基于链表的阻塞队列,使用2把锁来分别管理读和写,并发性能更好.
    new LinkedBlockingQueue(链表长度),默认Integer.MAX_VALUE
3. DelayQueue
  1. publicclassDelayQueue<E extendsDelayed>extendsAbstractQueue<E>
  2. implementsBlockingQueue<E>{
    延迟队列,没有长度限制,存的时候可以任意存,取的时候只有当指定的延迟时间到了,才能从队列中取到该元素;存的时候永远不会阻塞,只有取的时候才会阻塞.
4. SynchronousQueue
  1. publicclassSynchronousQueue<E>extendsAbstractQueue<E>
  2. implementsBlockingQueue<E>, java.io.Serializable{
   通俗点说,就是没有缓冲队列,取操作和存操作互相匹配到才会成功,否则就等待,直到互相匹配到. 
    一种无缓冲的等待队列,类似于无中介的直接交易,有点像原始社会中的生产者和消费者,生产者拿着产品去集市销售给产品的最终消费者,而消费者必须亲自去集市找到所要商品的直接生产者,如果一方没有找到合适的目标,那么对不起,大家都在集市等待。相对于有缓冲的BlockingQueue来说,少了一个中间经销商的环节(缓冲区),如果有经销商,生产者直接把产品批发给经销商,而无需在意经销商最终会将这些产品卖给那些消费者,由于经销商可以库存一部分商品,因此相对于直接交易模式,总体来说采用中间经销商的模式会吞吐量高一些(可以批量买卖);但另一方面,又因为经销商的引入,使得产品从生产者到消费者中间增加了额外的交易环节,单个产品的及时响应性能可能会降低。

  声明一个SynchronousQueue有两种不同的方式,它们之间有着不太一样的行为。公平模式和非公平模式的区别:

  如果采用公平模式:SynchronousQueue会采用公平锁,并配合一个FIFO队列来阻塞多余的生产者和消费者,从而体系整体的公平策略;

  但如果是非公平模式(SynchronousQueue默认):SynchronousQueue采用非公平锁,同时配合一个LIFO队列来管理多余的生产者和消费者,而后一种模式,如果生产者和消费者的处理速度有差距,则很容易出现饥渴的情况,即可能有某些生产者或者是消费者的数据永远都得不到处理。

    new SynchronousQueue(是否采用公平锁),默认false,非公平锁.

5. PriorityBlockingQueue
  1. publicclassPriorityBlockingQueue<E>extendsAbstractQueue<E>
  2. implementsBlockingQueue<E>, java.io.Serializable{
    基于优先级的阻塞队列(优先级的判断通过构造函数传入的Compator对象来决定),但需要注意的是PriorityBlockingQueue并不会阻塞数据生产者,而只会在没有可消费的数据时,阻塞数据的消费者。因此使用的时候要特别注意,生产者生产数据的速度绝对不能快于消费者消费数据的速度,否则时间一长,会最终耗尽所有的可用堆内存空间。在实现PriorityBlockingQueue时,内部控制线程同步的锁采用的是公平锁。
 
 
 
 
 
 
 
 
 
 
 
 

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值