日期:2025/04/05 12:36来源:未知 人气:54
对于 Java 中的队列, 主要是设计用在处理之前保存元素的集合。除了基本的集合操作外, 队列还提供了额外的插入、取数据和检查的工作。这些定义的方法每一种都有两种形式存在:一种是操作失败的时候抛出异常,另外一种返回特殊值,但是在大多数的使用情况下,插入操作不会抛出异常。 对于该接口操作中的元素通常以 FIFO 为基础进行排序。 通常情况下,队列不允许随机访问队列中的元素。
什么是队列?
队列是常用的数据结构之一,队列的元素或者成为数据, 有几个概念。
入队:在队列中插入数据元素叫做入队。
出队:从队列中删除(取出)数据元素叫做出队。
队头:在队列中取出数据元素的一端叫做队头。
队尾:在队列中插入数据元素的一端叫做队尾。
Queue 队列的定义
public interface Queue
当前接口扩展的方法如下:
现在说说这些方法的含义。
队列通常情况下以 FIFO 方法进行元素的排序。但是也有其他的队列,比方说: 优先级队列,使用提供的比较器进行元素排序的队列,或者元素的自然排序,当然也有后进后出的队列,它们对元素进行排序后进先出(),但是,无论使用什么顺序,队列的队头都是使用 remove() 和 poll() 方法对元素进行删除。并且在 FIFO 队列中,所有新进的元素都插入到了队列的尾部。
offer(E e) :对于该方法尽可能的插入一个元素,如果队列没有满返回 true, 否则将返回 false。
remove() 和 poll() :方法删除元素并返回队列的头。不过从哪个位置删除元素, 是根据队列的排序策略决定的。 remove 方法抛出异常,poll 返回 null。
element() 和 peek() :方法返回队列的头,但是不删除对应的元素数据。element 队列为空,抛出异常。 peek 队列为空,返回 null。
put(): 新增一个元素,假如队列满,则阻塞。
add(): 往队列中新增一个元素,如果队列已满, 则抛出异常。
为了方便使用抽象了 AbstractQueue 类。
定义:
publicabstractclassAbstractQueue
该队列由数组支持的有界阻塞队列, 此队列对元素的排序规则是:FIFO (先进先出)。对于该队列, 队列的头是停留时间最长的元素。队列的尾部是队列中存在时间最短的元素。新元素插入到队列的尾部,队列的检索是获取队列头部的元素。需要注意该队列是一个“有界的缓冲区”。 其中固定大小的数组保存由生产者插入,并由消费者提取元素。该队列一经创建, 容量就无法更改。使用 put() 方法将元素放入满的队列将导致操作阻塞。使用 take() 方法从空队列中尝试删除元素也会出现阻塞,一直等着有可用的元素操作。
该实现的定义:
publicclassArrayBlockingQueue
相关方法说明:
这个队列的演示有点麻烦。 尽量简单的来吧。
classPutQueueimplementsRunnable {
privateArrayBlockingQueue
publicPutQueue(ArrayBlockingQueue
inttime=9;
publicvoidrun() { while (time>=0) { try { System.out.println(" + 生产 ing"); queue.put(String.valueOf(time)); System.out.println(Thread.currentThread().getName() +":"+time--+" "+queue); Thread.sleep(1000); } catch (InterruptedExceptione) { e.printStackTrace(); } } } }
单独起两个线程, 一个入队, 一个出队,并且入队的间隔时间为 1 秒,而出队的时间为 5 秒。这样就会出现入队超过次数, 就在那等待。效果如下:
第一次生产直接就消费了, 是因为第一次起来的时候, 基本上是同时执行, 然后没有入队的时候, 出队已经在等待了。
需要注意 add 和 put 的区别。 add 方法演示如下:
该实现基于链表, 是一个有界的阻塞队列。该队列对元素默认使用 FIFO 的进行排序。对于链表实现的队列通常比基于阵列的队列有更高的吞吐量,数据的新增和移除速度比数组快。并且元素默认的容量大小是 Integer.MAX_VALUE 。在入队和出队时有分别独立的锁, 可以实现并行执行。
LinkedBlockingQueue 队列的定义:
publicclassLinkedBlockingQueue
实例演示:
只能体会其中的用法, 这个用法实际案例中不会使用。
在一些项目中使用的场景为:比方说消息的推送。把需要推送的用户信息全部放到队列中, 或者固定的数据, 放入队列, 然后使用消费发送的接口进行消费。 理解这个原理上, 在考虑一些实际场景中的问题, 慢慢的会发现, MQ 或者 Redis 队列都是有实际的业务场景最终封装出来的。当然还是那句话, 框架都是在业务的基础上更加易用,以及使用市面上更加认可的解决方案。
除了这两个还有另外的队列使用方式, 现在先不详解, 后续说过多线程和并发之后, 再来回头聊聊这个知识点。 学习要循序渐进。一口不可能吃个胖子, 想瘦也要有时间沉淀。
感谢阅读。 点赞,收藏, 关注。 后续更多内容持续输出中。
上一篇:Java打印数组的5种不同方法
下一篇:Java中的大对象怎么了?