0
点赞
收藏
分享

微信扫一扫

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

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

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

欢迎 点赞,关注,评论。

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

历史热点文章

  • 解锁大语言模型参数:零基础掌握大型语言模型参数奥秘与实践指南
  • 高性能连接池之HikariCP框架分析:高性能逐条分解(架构师篇)
  • 缓存雪崩/穿透/击穿/失效原理图/14种缓存数据特征+10种数据一致性方案
  • Java 8函数式编程全攻略:43种函数式业务代码实战案例解析(收藏版)
  • 一个项目代码讲清楚DO/PO/BO/AO/E/DTO/DAO/ POJO/VO
  • 17个Mybatis Plugs注解:Mybatis Plugs插件架构设计与注解案例(必须收藏)

LinkedListQueue(业务结构)

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

1、设计思考:
  1. 需求场景
    • 在许多编程任务中,需要一个能够快速进行插入和删除操作的队列结构。例如,在实现缓冲区管理、任务调度、消息队列等应用中,快速的入队和出队操作是非常重要的。
  2. 现有技术局限性
    • 传统的数组类型在 Java 中是固定长度的,一旦创建,其大小不能改变,这限制了其在需要动态大小管理时的使用。
    • Vector 类似于 ArrayList,但它是线程安全的,使用 synchronized 进行同步,导致并发性能较差。
    • ArrayDeque 提供了双端队列功能,但在某些情况下,可能需要进行数组的扩容或缩容操作。
  3. 技术融合
    • LinkedListQueue 结合了 LinkedList 的高效插入和删除特性,并提供了队列所需的先进先出(FIFO)的数据管理方式。它通过链表的双向链接特性,允许从两端快速地添加或移除元素,特别适合实现队列和双端队列。
  4. 设计理念
    • LinkedListQueue 通过使用链表结构,可以有效地进行插入和删除操作,因为这些操作仅需要改变节点的指针,而不需要移动整个数组。它实现了 Queue 接口,提供了队列所需的所有操作,包括 offerpollpeek 等。
  5. 实现方式
    • 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");
        }
    }
}
举报

相关推荐

0 条评论