Queue接口分析
一、Queue是什么
该接口时Java集合框架成员
Queue: 通常(但不一定)队列就是一个先入先出(FIFO)的数据结构,和堆一样(但可以进行转换,比如优先级列队排序,又或者改为栈形式的后进先出数据结构, 不论如何,都可以用remove()或poll()来调节)
Queue接口与List、Set同一级别,都是继承了Collection接口。
LinkedList实现的Deque接口中继承了Queue,所以在LinkedList中就有Queue重写的方法,同时也可以多态的声明Queue队列对象
队列实现通常不允许插入null,但不禁止插入null
二、Queue的实现
1、没有实现的阻塞接口的LinkedList: 实现了java.util.Queue接口和java.util.AbstractQueue接口
内置的不阻塞队列: PriorityQueue 和 ConcurrentLinkedQueue
PriorityQueue 和 ConcurrentLinkedQueue 类在 Collection Framework 中加入两个具体集合实现。
PriorityQueue 类实质上维护了一个有序列表。加入到 Queue 中的元素根据它们的天然排序(通过其 java.util.Comparable 实现)或者根据传递给构造函数的 java.util.Comparator 实现来定位。
ConcurrentLinkedQueue 是基于链接节点的、线程安全的队列。并发访问不需要同步。因为它在队列的尾部添加元素并从头部删除它们,所以只要不需要知道队列的大 小, ConcurrentLinkedQueue 对公共集合的共享访问就可以工作得很好。收集关于队列大小的信息会很慢,需要遍历队列。
2)实现阻塞接口的:
java.util.concurrent 中加入了 BlockingQueue 接口和五个阻塞队列类。它实质上就是一种带有一点扭曲的 FIFO 数据结构。不是立即从队列中添加或者删除元素,线程执行操作阻塞,直到有空间或者元素可用。
五个队列所提供的各有不同:
* ArrayBlockingQueue :一个由数组支持的有界队列。
* LinkedBlockingQueue :一个由链接节点支持的可选有界队列。
* PriorityBlockingQueue :一个由优先级堆支持的无界优先级队列。
* DelayQueue :一个由优先级堆支持的、基于时间的调度队列。
* SynchronousQueue :一个利用 BlockingQueue 接口的简单聚集(rendezvous)机制。
下表显示了jdk1.5中的阻塞队列的操作:
add 增加一个元索 如果队列已满,则抛出一个IIIegaISlabEepeplian异常
remove 移除并返回队列头部的元素 如果队列为空,则抛出一个NoSuchElementException异常
element 返回队列头部的元素 如果队列为空,则抛出一个NoSuchElementException异常
offer 添加一个元素并返回true 如果队列已满,则返回false
poll 移除并返问队列头部的元素 如果队列为空,则返回null
peek 返回队列头部的元素 如果队列为空,则返回null
put 添加一个元素 如果队列满,则阻塞
take 移除并返回队列头部的元素 如果队列为空,则阻塞
remove、element、offer 、poll、peek 其实是属于Queue接口。
阻塞队列的操作可以根据它们的响应方式分为以下三类:aad、removee和element操作在你试图为一个已满的队列增加元素或从空队列取得元素时 抛出异常。当然,在多线程程序中,队列在任何时间都可能变成满的或空的,所以你可能想使用offer、poll、peek方法。这些方法在无法完成任务时 只是给出一个出错示而不会抛出异常。
注意:poll和peek方法出错进返回null。因此,向队列中插入null值是不合法的
最后,我们有阻塞操作put和take。put方法在队列满时阻塞,take方法在队列空时阻塞。
LinkedBlockingQueue的容量是没有上限的(说的不准确,在不指定时容量为Integer.MAX_VALUE,不要然的话在put时怎么会受阻呢),但是也可以选择指定其最大容量,它是基于链表的队列,此队列按 FIFO(先进先出)排序元素。
ArrayBlockingQueue在构造时需要指定容量, 并可以选择是否需要公平性,如果公平参数被设置true,等待时间最长的线程会优先得到处理(其实就是通过将ReentrantLock设置为true来 达到这种公平性的:即等待时间最长的线程会先操作)。通常,公平性会使你在性能上付出代价,只有在的确非常需要的时候再使用它。它是基于数组的阻塞循环队 列,此队列按 FIFO(先进先出)原则对元素进行排序。
PriorityBlockingQueue是一个带优先级的 队列,而不是先进先出队列。元素按优先级顺序被移除,该队列也没有上限(看了一下源码,PriorityBlockingQueue是对 PriorityQueue的再次包装,是基于堆数据结构的,而PriorityQueue是没有容量限制的,与ArrayList一样,所以在优先阻塞 队列上put时是不会受阻的。虽然此队列逻辑上是无界的,但是由于资源被耗尽,所以试图执行添加操作可能会导致 OutOfMemoryError),但是如果队列为空,那么取元素的操作take就会阻塞,所以它的检索操作take是受阻的。另外,往入该队列中的元 素要具有比较能力。
DelayQueue(基于PriorityQueue来实现的)是一个存放Delayed 元素的无界阻塞队列,只有在延迟期满时才能从中提取元素。该队列的头部是延迟期满后保存时间最长的 Delayed 元素。如果延迟都还没有期满,则队列没有头部,并且poll将返回null。当一个元素的 getDelay(TimeUnit.NANOSECONDS) 方法返回一个小于或等于零的值时,则出现期满,poll就以移除这个元素了。此队列不允许使用 null 元素。
三、案例
1.算法案例
/**
* 入口
* 101. 对称二叉树
* 1.创建链表root
* 输入:
* TreeNode root = [1,2,2,3,4,4,3]
* 输出:
* result = true
* 解释:
* 1.递归
* 2.迭代(Queue队列)
*/
@Test
public void suanfa21()
{
// 创建树
TreeNode root = new TreeNode(1, new TreeNode(2, new TreeNode(3), new TreeNode(4)), new TreeNode(2, new TreeNode(4), new TreeNode(3)));// 调用方法:迭代
boolean result2 = this.isSymmetricIteration(root);
System.out.println("results2 = " + result2); } /**
* 迭代方案
*
* @param root 二叉树
* @return
*/
public boolean isSymmetricIteration(TreeNode root)
{
// Queue队列 和 堆的处理方案一样,都是先进先出(FIFO)的数据结构
Queue<TreeNode> treeNodes = new LinkedList<>(); // 存入根节点的 左子树 和 右子树
treeNodes.offer(root.left);
treeNodes.offer(root.right); // 如果Queue队列不为空就循环比较
while (!treeNodes.isEmpty())
{
// 获取存入的左子树 和 右子树 (因为先进先出,所以可以确认顺序)
TreeNode rootLeft = treeNodes.poll();
TreeNode rootRight = treeNodes.poll(); // 两个都等于null, 所以没有子节点了,就继续判断队列中是否还有值,有则比较,无则结束,返回true
if (rootLeft == null && rootRight == null)
{
continue;
} // 左子树 或 右子树,如果有一个是null,就说明不相等,直接返回false,因为上面的判断,所以不可能两个都是null
if (rootLeft == null || rootRight == null)
{
return false;
} // 左子树 比较 右子树 的值不相等,直接返回false
if (rootLeft.val != rootRight.val)
{
return false;
} // 存入 左子树的左子树 和 右子树的右子树,这样当取出比较相等就说明是镜像
treeNodes.offer(rootLeft.left);
treeNodes.offer(rootRight.right); // 存入 左子树的右子树 和 右子树的左子树,这样当取出比较相等就说明是镜像
treeNodes.offer(rootLeft.right);
treeNodes.offer(rootRight.left);
}
// 当执行到这里说明树两边是镜像的
return true;
}
2.多线程案例
package com.yao;
import java.util.concurrent.ArrayBlockingQueue;
import java.util.concurrent.BlockingQueue;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
public class BlockingQueueTest {
/**
定义装苹果的篮子
*/
public static class Basket{
// 篮子,能够容纳3个苹果
BlockingQueue<String> basket = new ArrayBlockingQueue<String>(3); // 生产苹果,放入篮子
public void produce() throws InterruptedException{
// put方法放入一个苹果,若basket满了,等到basket有位置
basket.put("An apple");
}
// 消费苹果,从篮子中取走
public String consume() throws InterruptedException{
// get方法取出一个苹果,若basket为空,等到basket有苹果为止
String apple = basket.take();
return apple;
} public int getAppleNumber(){
return basket.size();
} }
// 测试方法
public static void testBasket() {
// 建立一个装苹果的篮子
final Basket basket = new Basket();
// 定义苹果生产者
class Producer implements Runnable {
public void run() {
try {
while (true) {
// 生产苹果
System.out.println("生产者准备生产苹果:"
+ System.currentTimeMillis());
basket.produce();
System.out.println("生产者生产苹果完毕:"
+ System.currentTimeMillis());
System.out.println("生产完后有苹果:"+basket.getAppleNumber()+"个");
// 休眠300ms
Thread.sleep(300);
}
} catch (InterruptedException ex) {
}
}
}
// 定义苹果消费者
class Consumer implements Runnable {
public void run() {
try {
while (true) {
// 消费苹果
System.out.println("消费者准备消费苹果:"
+ System.currentTimeMillis());
basket.consume();
System.out.println("消费者消费苹果完毕:"
+ System.currentTimeMillis());
System.out.println("消费完后有苹果:"+basket.getAppleNumber()+"个");
// 休眠1000ms
Thread.sleep(1000);
}
} catch (InterruptedException ex) {
}
}
} ExecutorService service = Executors.newCachedThreadPool();
Producer producer = new Producer();
Consumer consumer = new Consumer();
service.submit(producer);
service.submit(consumer);
// 程序运行10s后,所有任务停止
try {
Thread.sleep(10000);
} catch (InterruptedException e) {
}
service.shutdownNow();
}
public static void main(String[] args) {
BlockingQueueTest.testBasket();
}
}
参考:https://www.cnblogs.com/lemon-flm/p/7877898.html
Queue接口分析的更多相关文章
- Queue接口分析:add和offer区别,remove和poll方法到底啥区别
Queue接口: public interface Queue<E> extends Collection<E> { /* * add方法,在不违背队列的容量限制的情况,往队列 ...
- [数据结构]——链表(list)、队列(queue)和栈(stack)
在前面几篇博文中曾经提到链表(list).队列(queue)和(stack),为了更加系统化,这里统一介绍着三种数据结构及相应实现. 1)链表 首先回想一下基本的数据类型,当需要存储多个相同类型的数据 ...
- Azure Queue Storage 基本用法 -- Azure Storage 之 Queue
Azure Storage 是微软 Azure 云提供的云端存储解决方案,当前支持的存储类型有 Blob.Queue.File 和 Table. 笔者在<Azure File Storage 基 ...
- C++ std::queue
std::queue template <class T, class Container = deque<T> > class queue; FIFO queue queue ...
- 初识Message Queue之--基础篇
之前我在项目中要用到消息队列相关的技术时,一直让Redis兼职消息队列功能,一个偶然的机会接触到了MSMQ消息队列.秉着技术还是专业的好为原则,对MSMQ进行了学习,以下是我个人的学习笔记. 一.什么 ...
- 搭建高可用的rabbitmq集群 + Mirror Queue + 使用C#驱动连接
我们知道rabbitmq是一个专业的MQ产品,而且它也是一个严格遵守AMQP协议的玩意,但是要想骚,一定需要拿出高可用的东西出来,这不本篇就跟大家说 一下cluster的概念,rabbitmq是erl ...
- PriorityQueue和Queue的一种变体的实现
队列和优先队列是我们十分熟悉的数据结构.提供了所谓的“先进先出”功能,优先队列则按照某种规则“先进先出”.但是他们都没有提供:“固定大小的队列”和“固定大小的优先队列”的功能. 比如我们要实现:记录按 ...
- C#基础---Queue(队列)的应用
Queue队列,特性先进先出. 在一些项目中我们会遇到对一些数据的Check,如果数据不符合条件将会把不通过的信息返回到界面.但是对于有的数据可能会Check很多条件,如果一个数据一旦很多条件不 ...
- [LeetCode] Queue Reconstruction by Height 根据高度重建队列
Suppose you have a random list of people standing in a queue. Each person is described by a pair of ...
- [LeetCode] Implement Queue using Stacks 用栈来实现队列
Implement the following operations of a queue using stacks. push(x) -- Push element x to the back of ...
随机推荐
- 理解ID3决策树
决策树是一个树形结构,类似下面这样: 上图除了根节点外,有三个叶子节点和一个非叶子节点. 在解决分类问题的决策树中,叶子节点就表示所有的分类,比如这里的分类就有3种:无聊时阅读的邮件.需及时处理的邮件 ...
- C语言的头文件包含,竟存在这么多知识点!
文章来自:https://zhuanlan.zhihu.com/p/472808057 相关文章连接:头文件包含是可以嵌套的_[C语言]- 预处理指令3 - 文件包含! 很多事不深入以为自己懂了,但真 ...
- N-gram基本原理
N-gram模型是一种语言模型(Language Model,LM),语言模型是一个基于概率的判别模型,它的输入是一句话(单词的顺序序列),输出是这句话的概率,即这些单词的联合概率(joint pro ...
- mybatis - [04] mapper文件详解
Mybatis的Mapper文件(通常是以.xml为扩展名的文件)主要用于定义SQL语句和它们与Java接口方法之间的映射关系.以下是Mapper文件中一些常用的配置元素和属性. 一.mapper ...
- Flume - [02] Spooling Directory Source
一.概述 可以通过将文件放入磁盘上的 "Spooldir" 目录中来获取数据.此源会监视指定目录中的新文件,并在新文件出现时解析新文件中的事件.事件解析逻辑是可插入的.在将指定 ...
- Obsidian + DeepSeek:免费 AI 助力你的知识管理,让你的笔记飞起来!
Obsidian + DeepSeek:免费 AI 助力你的知识管理,让你的笔记飞起来! 1. 优势介绍 Obsidian 是一款强大的本地知识管理软件,它像一个积木盒,让你用 Markdown 笔记 ...
- python 二级 语言基本元素笔记-字符串
l='12345' 1.递增顺序: 正向递增从0开始 负向从[-1]开始,l[1]=2,l[-1]=5 2.切片操作:左开右闭,l[2:5]=3,4 3.导入库,引入 库名.函数名 input函数 输 ...
- SICK Ranger3源码分析——断线重连
前言 本文可在https://paw5zx.github.io/SICK-Ranger3-source-code-analysis-01/中阅读,体验更加 简单分析一下SICK Ranger3源码中断 ...
- 2个月搞定计算机二级C语言——真题(11)解析
1. 前言 今天双 11,正好轮到讲第 11 篇,直接来个三 11. 那么本篇我们讲解2个月搞定计算机二级C语言--真题11 2. 程序填空题 2.1 题目要求 2.2 提供的代码 #include ...
- deepseek内网离线部署手册
前言 在当下 AI 浪潮汹涌的时代,DeepSeek 以其卓越的性能和出色的表现,迅速成为了众多专业人士和科技爱好者热议的焦点工具.在众多AI大模型的比拼中,DeepSeek 展现出了优越的实力.然而 ...