java的队列

java的阻塞队列是线程安全的,底层使用ReentrantLock实现了线程安全。是一种典型的生成者消费者模式。

1. ArrayBlockingQueue :由数组结构组成的有界阻塞队列。

2. LinkedBlockingQueue :由链表结构组成的有界阻塞队列。

3. PriorityBlockingQueue :支持优先级排序的无界阻塞队列。

4. DelayQueue:使用优先级队列实现的无界阻塞队列。

5. SynchronousQueue:不存储元素的阻塞队列。

6. LinkedTransferQueue:由链表结构组成的无界阻塞队列。

7. LinkedBlockingDeque:由链表结构组成的双向阻塞队列
 

 add:添加元素到队列里,添加成功返回true,由于容量满了添加失败会抛出IllegalStateException异常

offer:添加元素到队列里,添加成功返回true,添加失败返回false

put:添加元素到队列里,如果容量满了会阻塞直到容量不满 3个删除方法。

poll:删除队列头部元素,如果队列为空,返回null。否则返回元素。

remove:基于对象找到对应的元素,并删除。删除成功返回true,否则返回false

take:删除队列头部元素,如果队列为空,一直阻塞到队列有元素并删除 

ArrayBlockingQueue 为例:

public class ArrayBlockingQueue<E> extends AbstractQueue<E>
        implements BlockingQueue<E>, java.io.Serializable {

    final Object[] items; //元素数组(循环队列)

    int takeIndex; //队首元素下标

    int putIndex;//队尾的下一个位置下标

    int count;//元素数量

    final ReentrantLock lock;  //保证并发安全

    private final Condition notEmpty;  //消费者队列

    private final Condition notFull; //生成者队列

    transient Itrs itrs;
}

ArrayBlockingQueue*(公平、非公平)**
用数组实现的有界阻塞队列。此队列按照先进先出(FIFO)的原则对元素进行排序。默认情况下不保证 访问者公平的访问队列,所谓公平访问队列是指阻塞的所有生产者线程或消费者线程,当队列可用时, 可以按照阻塞的先后顺序访问队列,即先阻塞的生产者线程,可以先往队列里插入元素,先阻塞的消费 者线程,可以先从队列里获取元素。通常情况下为了保证公平性会降低吞吐量。我们可以使用以下代码 创建一个公平的阻塞队列: ArrayBlockingQueue fairQueue = new ArrayBlockingQueue(1000,true);

LinkedBlockingQueue*(两个独立锁提高并发)** 
基于链表的阻塞队列,同ArrayListBlockingQueue类似,此队列按照先进先出(FIFO)的原则对元素进 行排序。而 LinkedBlockingQueue 之所以能够高效的处理并发数据,还因为其对于生产者端和消费者 端分别采用了独立的锁来控制数据同步,这也意味着在高并发的情况下生产者和消费者可以并行地操作 队列中的数据,以此来提高整个队列的并发性能。
LinkedBlockingQueue 会默认一个类似无限大小的容量(Integer.MAX_VALUE)。 
PriorityBlockingQueue*(*compareTo 排序实现优先*)** 是一个支持优先级的无界队列。默认情况下元素采取自然顺序升序排列。可以自定义实现 compareTo() 方法来指定元素进行排序规则,或者初始化 PriorityBlockingQueue 时,指定构造参数 Comparator 来 对元素进行排序。需要注意的是不能保证同优先级元素的顺序。


DelayQueue*(缓存失效、定时任务 )** 
是一个支持延时获取元素的无界阻塞队列。队列使用PriorityQueue来实现。队列中的元素必须实现 Delayed 接口,在创建元素时可以指定多久才能从队列中获取当前元素。只有在延迟期满时才能从队列 中提取元素。我们可以将 DelayQueue 运用在以下应用场景: 1. 缓存系统的设计:可以用 DelayQueue 保存缓存元素的有效期,使用一个线程循环查询
DelayQueue,一旦能从 DelayQueue 中获取元素时,表示缓存有效期到了。 2. 定时任务调度:使用 DelayQueue 保存当天将会执行的任务和执行时间,一旦从
DelayQueue 中获取到任务就开始执行,从比如 TimerQueue 就是使用 DelayQueue 实现的。 SynchronousQueue*(不存储数据、可用于传递数据)** 
是一个不存储元素的阻塞队列。每一个 put 操作必须等待一个 take 操作,否则不能继续添加元素。 SynchronousQueue 可以看成是一个传球手,负责把生产者线程处理的数据直接传递给消费者线程。队 列本身并不存储任何元素,非常适合于传递性场景,比如在一个线程中使用的数据,传递给另 外 一 个 线 程 使 用 , SynchronousQueue 的 吞 吐 量 高 于 LinkedBlockingQueue 和 ArrayBlockingQueue。 
LinkedTransferQueue 是 一 个 由 链 表 结 构 组 成 的 无 界 阻 塞 TransferQueue 队 列 。 相 对 于 其 他 阻 塞 队 列 ,
LinkedTransferQueue 多了 tryTransfer 和 transfer 方法。 1. transfer 方法:如果当前有消费者正在等待接收元素(消费者使用 take()方法或带时间限制的 poll()方法时),transfer 方法可以把生产者传入的元素立刻 transfer(传输)给消费者。如果没有 消费者在等待接收元素,transfer 方法会将元素存放在队列的 tail 节点,并等到该元素被消费者消 费了才返回。 2. tryTransfer 方法。则是用来试探下生产者传入的元素是否能直接传给消费者。如果没有消费者等 待接收元素,则返回 false。和 transfer 方法的区别是 tryTransfer 方法无论消费者是否接收,方 法立即返回。而 transfer 方法是必须等到消费者消费了才返回。 对于带有时间限制的 tryTransfer(E e, long timeout, TimeUnit unit)方法,则是试图把生产者传入的元 素直接传给消费者,但是如果没有消费者消费该元素则等待指定的时间再返回,如果超时还没消费元 素,则返回 false,如果在超时时间内消费了元素,则返回 true。 
LinkedBlockingDeque 
是一个由链表结构组成的双向阻塞队列。所谓双向队列指的你可以从队列的两端插入和移出元素。
双端队列因为多了一个操作队列的入口,在多线程同时入队时,也就减少了一半的竞争。相比其他的阻 塞队列,LinkedBlockingDeque 多了 addFirst,addLast,offerFirst,offerLast, peekFirst, peekLast 等方法,以 First 单词结尾的方法,表示插入,获取(peek)或移除双端队列的第一个元素。 以 Last 单词结尾的方法,表示插入,获取或移除双端队列的后一个元素。另外插入方法 add 等同于 addLast,移除方法 remove 等效于 removeFirst。但是 take 方法却等同于 takeFirst,不知道是不是 Jdk 的 bug,使用时还是用带有 First 和 Last 后的方法更清楚。 
在初始化 LinkedBlockingDeque 时可以设置容量防止其过渡膨胀。另外双向阻塞队列可以运用在 “工作窃取”模式中。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值