写点什么

图解 LinkedListQueue 数据结构设计与应用案例

作者:肖哥弹架构
  • 2024-10-19
    河北
  • 本文字数:2780 字

    阅读完需:约 9 分钟

图解LinkedListQueue数据结构设计与应用案例


LinkedListQueue 是 Java 中基于 LinkedList 实现的队列,支持 FIFO(先进先出)的数据结构。它允许在队列的头部和尾部高效地进行元素的插入和删除操作。由于 LinkedListQueue 继承自 LinkedList,它具有动态数组的特性,能够根据需要自动调整大小。在多线程环境中,通常使用 LinkedBlockingQueue 作为线程安全的队列实现。


肖哥弹架构 跟大家“弹弹” 高并发锁, 关注公号回复 'mvcc' 获得手写数据库事务代码

欢迎 点赞,关注,评论。

关注公号 Solomon 肖哥弹架构获取更多精彩内容

历史热点文章

LinkedListQueue(业务结构)

LinkedListQueue 是一个基于链表实现的队列,它通常由一个双向链表构成,支持在队列的前端(头部)进行出队操作,以及在队列的后端(尾部)进行入队操作。

1、设计思考:

  1. 需求场景

  2. 在许多编程任务中,需要一个能够快速进行插入和删除操作的队列结构。例如,在实现缓冲区管理、任务调度、消息队列等应用中,快速的入队和出队操作是非常重要的。

  3. 现有技术局限性

  4. 传统的数组类型在 Java 中是固定长度的,一旦创建,其大小不能改变,这限制了其在需要动态大小管理时的使用。

  5. Vector 类似于 ArrayList,但它是线程安全的,使用 synchronized 进行同步,导致并发性能较差。

  6. ArrayDeque 提供了双端队列功能,但在某些情况下,可能需要进行数组的扩容或缩容操作。

  7. 技术融合

  8. LinkedListQueue 结合了 LinkedList 的高效插入和删除特性,并提供了队列所需的先进先出(FIFO)的数据管理方式。它通过链表的双向链接特性,允许从两端快速地添加或移除元素,特别适合实现队列和双端队列。

  9. 设计理念

  10. LinkedListQueue 通过使用链表结构,可以有效地进行插入和删除操作,因为这些操作仅需要改变节点的指针,而不需要移动整个数组。它实现了 Queue 接口,提供了队列所需的所有操作,包括 offerpollpeek 等。

  11. 实现方式

  12. LinkedListQueue 由一系列 Node 对象组成,每个 Node 包含数据和两个引用(previousnext),分别指向前一个和后一个节点。它提供了 enqueue(入队)和 dequeue(出队)操作,以及查看队列头部和尾部元素的方法,而不需要遍历整个链表。

2、数据结构

图说明:
  • LinkedListQueue

  • 表示 LinkedListQueue 类的实例,是一个基于链表的队列数据结构。

  • head

  • 表示队列的头节点,它指向队列中的第一个元素,用于出队操作。

  • tail

  • 表示队列的尾节点,它指向队列中的最后一个元素,用于入队操作。

  • Node

  • 链表中的节点,包含数据和两个引用,分别指向前一个节点和后一个节点。

  • data

  • 节点中存储的数据。

  • prev

  • 节点的前驱引用,指向前一个节点。

  • next

  • 节点的后继引用,指向后一个节点。

3、执行流程

图说明:
  • 开始:执行操作的起始点。

  • 创建 LinkedListQueue 实例:初始化 LinkedListQueue 对象。

  • 入队操作:执行将元素添加到队列尾部的操作。

  • 添加元素到队尾:在队列的尾部添加新元素。

  • 结束入队:完成入队操作。

  • 出队操作:执行将元素从队列头部移除的操作。

  • 移除队首元素:从队列头部移除元素。

  • 结束出队:完成出队操作。

  • 遍历队列:从头到尾遍历队列中的所有元素。

  • 从头节点开始:从队列的头节点开始遍历。

  • 访问每个节点:顺序访问链表中的每个节点。

  • 读取节点数据:读取每个节点中存储的数据。

  • 结束遍历:完成队列遍历。

  • 结束:所有操作完成。

4、优点

  • 高效的插入/删除操作:在队列的两端插入和删除元素的时间复杂度为 O(1)。

  • 允许空队列:与某些数组实现的队列不同,LinkedListQueue 允许空队列存在,不会因为空数组而抛出异常。

  • 能够作为队列和双端队列使用:提供了实现队列和双端队列所需的方法。

5、缺点

  • 随机访问性能差:由于链表的结构,随机访问元素的时间复杂度为 O(n)。

  • 内存开销:相比于数组实现的队列,LinkedListQueue 需要额外的内存来存储节点的指针。

6、使用场景

  • 需要快速插入和删除元素的场景,如实现一个消息队列。

  • 作为队列或双端队列使用,特别是在需要从两端进行元素添加或移除的操作中。

7、类设计

8、应用案例

在这个案例中,我们将使用 LinkedListQueue 来实现一个简单的打印任务队列。这个队列将按照先进先出的顺序处理任务。


import java.util.concurrent.BlockingQueue;import java.util.concurrent.LinkedBlockingQueue;
// 任务类,实现了Runnable接口,用于表示具体任务class PrintTask implements Runnable { private final String taskName;
public PrintTask(String taskName) { this.taskName = taskName; }
@Override public void run() { // 任务执行时间 try { System.out.println("Task " + taskName + " is running"); Thread.sleep(2000); // 任务执行需要一些时间 } catch (InterruptedException e) { Thread.currentThread().interrupt(); System.out.println("Task " + taskName + " was interrupted"); } System.out.println("Task " + taskName + " finished"); }}
public class LinkedListQueueExample { public static void main(String[] args) { // 创建一个LinkedListQueue实例,用作任务队列 BlockingQueue<Runnable> taskQueue = new LinkedBlockingQueue<>();
// 添加任务到队列 taskQueue.offer(new PrintTask("Task 1")); taskQueue.offer(new PrintTask("Task 2")); taskQueue.offer(new PrintTask("Task 3"));
// 创建并启动一个新线程来处理队列中的任务 new Thread(() -> { while (true) { try { // 从队列中取出一个任务并执行 taskQueue.take().run(); } catch (InterruptedException e) { Thread.currentThread().interrupt(); System.out.println("Task processing was interrupted"); break; } } }).start();
// 主线程继续执行其他任务或等待子线程完成 try { Thread.sleep(6000); // 等待足够长的时间以确保所有任务都已完成 } catch (InterruptedException e) { Thread.currentThread().interrupt(); System.out.println("Main thread was interrupted"); } }}
复制代码


发布于: 刚刚阅读数: 4
用户头像

智慧属心窍之锁 2019-05-27 加入

擅长于通信协议、微服务架构、框架设计、消息队列、服务治理、PAAS、SAAS、ACE\ACP、大模型

评论

发布
暂无评论
图解LinkedListQueue数据结构设计与应用案例_Java_肖哥弹架构_InfoQ写作社区