当前位置: 首页 > news >正文

【C# 数据结构】队列 FIFO

目录

  • 队列的概念
  • FIFO (First-In, First-Out)
      • `Queue<T>` 的工作原理:
      • 示例:
        • 解释:
      • 小结:
  • 环形队列
      • 1. **FIFO?**
      • 2. **环形缓冲队列如何实现FIFO?**
        • 关键概念:
      • 3. **环形缓冲队列的工作过程**
        • 假设:
        • 操作步骤:
      • 4. **具体例子**
        • 初始状态:
        • 操作1:入队数据 `A`
        • 操作2:入队数据 `B`
        • 操作3:出队
        • 操作4:入队数据 `C`, `D`, `E`
        • 操作5:出队
        • 操作6:入队数据 `F`
        • 操作7:出队
      • 5. **环形缓冲队列的FIFO特性**
      • 6. **环形缓冲队列的FIFO优势**
      • 7. **小结**
  • C# 如何通过代码实现环状队列?
      • 1. **使用 `Queue<T>` 实现环形缓冲队列**
      • 使用示例:
      • 说明:
      • 2. **使用固定大小数组实现环形缓冲队列**
      • 使用示例:
      • 说明:
      • 小结
  • 队列和环状队列的对比
      • 1. **环形缓冲队列是FIFO的一种实现**
      • 2. **环形缓冲队列的特点**
      • 3. **环形缓冲队列 vs 其他FIFO实现**
      • 4. **环形缓冲队列的局限性**
      • 5. **小结**
  • 线程安全问题
      • Queue<T> 如果一个线程只负责写,一个线程只负责读会有问题吗?
      • 问题原因:
      • 一些潜在的风险:
      • 如何解决?
        • 1. 使用锁 (`lock`)
        • 2. 使用 `ConcurrentQueue<T>`
      • 总结:

队列的概念

队列和FIFO是什么关系?队列是一种数据结构。
FIFO是队列需要遵循的基本原则:First-In, First-Out。或者说FIFO是队列的基本特性!
C#中有个类叫做Queue,就是实现了队列这种数据结构的类,它遵循FIFO这个原则。

FIFO (First-In, First-Out)

FIFO(First In First Out,先进先出)是一种数据管理原则,就像排队一样:

  • 先进入队列的数据先被处理
  • 后进入队列的数据后被处理

在 FIFO 队列中,第一个进入队列的元素将是第一个被移除的元素。换句话说,队列中的元素按照它们被加入的顺序排列,最早加入的元素最先被取出。

Queue<T> 的工作原理:

  • 入队 (Enqueue):新元素被添加到队列的尾部。
  • 出队 (Dequeue):最早加入队列的元素从队列的头部移除,并返回该元素。

示例:

假设我们使用一个容量为 3 的队列,依次加入元素 123,然后进行 Dequeue() 操作:

Queue<int> queue = new Queue<int>();// 入队操作
queue.Enqueue(1);
queue.Enqueue(2);
queue.Enqueue(3);// 出队操作,按照 FIFO 顺序返回
Console.WriteLine(queue.Dequeue()); // 输出 1
Console.WriteLine(queue.Dequeue()); // 输出 2
Console.WriteLine(queue.Dequeue()); // 输出 3
解释:
  • Enqueue(1)1 加入队列的尾部。
  • Enqueue(2)2 加入队列的尾部。
  • Enqueue(3)3 加入队列的尾部。
  • Dequeue() 返回并移除队列的头部元素,即最早加入的 1,然后是 23,遵循 FIFO 的顺序。

小结:

通过Queue<T> 的使用我们可以很好的理解 FIFO ,其中元素按照加入的顺序进行排队,最早加入的元素最先被取出。这使得它特别适用于处理排队和任务调度等场景。

环形队列


1. FIFO?

环状队列也是队列的一种,当然也遵循FIFO这个原则!

2. 环形缓冲队列如何实现FIFO?

环形缓冲队列是一种用固定大小的数组实现FIFO的方式。它通过两个指针(头指针和尾指针)来管理数据的入队和出队。

关键概念:
  • 固定大小的数组:预分配一块连续的内存空间。
  • 头指针(head):指向下一个数据写入的位置。
  • 尾指针(tail):指向下一个数据读取的位置。
  • 循环利用:当指针到达数组末尾时,会回到数组开头,形成一个“环”。

3. 环形缓冲队列的工作过程

让我们通过一个具体的例子来说明。

假设:
  • 环形缓冲队列的容量为 5(即数组大小为5)。
  • 初始状态:队列为空,headtail 都指向位置 0
操作步骤:
  1. 入队(Enqueue)

    • 将数据写入 head 指向的位置。
    • 然后 head 向前移动一位。
    • 如果 head 到达数组末尾,它会回到数组开头(循环特性)。
  2. 出队(Dequeue)

    • tail 指向的位置读取数据。
    • 然后 tail 向前移动一位。
    • 如果 tail 到达数组末尾,它会回到数组开头。

4. 具体例子

初始状态:
数组索引: [0]  [1]  [2]  [3]  [4]
值:      None None None None None
head = 0, tail = 0
操作1:入队数据 A
  • A 写入 head 指向的位置(索引 0)。
  • head 移动到下一个位置(索引 1)。
数组索引: [0]  [1]  [2]  [3]  [4]
值:       A    None None None None
head = 1, tail = 0
操作2:入队数据 B
  • B 写入 head 指向的位置(索引 1)。
  • head 移动到下一个位置(索引 2)。
数组索引: [0]  [1]  [2]  [3]  [4]
值:       A     B    None None None
head = 2, tail = 0
操作3:出队
  • tail 指向的位置(索引 0)读取数据 A
  • tail 移动到下一个位置(索引 1)。
数组索引: [0]  [1]  [2]  [3]  [4]
值:       A     B    None None None
head = 2, tail = 1
操作4:入队数据 C, D, E
  • 依次将 C, D, E 写入 head 指向的位置。
  • head 移动到下一个位置。
数组索引: [0]  [1]  [2]  [3]  [4]
值:       A     B     C     D     E
head = 0, tail = 1
操作5:出队
  • tail 指向的位置(索引 1)读取数据 B
  • tail 移动到下一个位置(索引 2)。
数组索引: [0]  [1]  [2]  [3]  [4]
值:       A     B     C     D     E
head = 0, tail = 2
操作6:入队数据 F
  • F 写入 head 指向的位置(索引 0)。
  • head 移动到下一个位置(索引 1)。
数组索引: [0]  [1]  [2]  [3]  [4]
值:       F     B     C     D     E
head = 1, tail = 2
操作7:出队
  • tail 指向的位置(索引 2)读取数据 C
  • tail 移动到下一个位置(索引 3)。
数组索引: [0]  [1]  [2]  [3]  [4]
值:       F     B     C     D     E
head = 1, tail = 3

5. 环形缓冲队列的FIFO特性

  • 数据顺序:先入队的数据(如 A, B)先出队,后入队的数据(如 C, D, E)后出队。
  • 循环利用:当 headtail 到达数组末尾时,会回到数组开头,继续使用之前释放的空间。
  • 固定容量:队列的大小是固定的,当队列满时,可以选择覆盖旧数据或报错。

6. 环形缓冲队列的FIFO优势

  • 高效:入队和出队操作的时间复杂度都是 O(1)。
  • 内存紧凑:数据连续存储,缓存友好。
  • 适合实时系统:适合处理固定大小的数据流。

7. 小结

  • 环形缓冲队列是FIFO的一种实现,它通过固定大小的数组和循环指针来实现先进先出的特性。
  • 数据按顺序入队和出队,先进入队列的数据先被处理。
  • 循环利用使得内存使用更高效,适合处理固定大小的数据流。
    通过理解环状队列你是不是对队列又有了更深的理解呢? 😊

C# 如何通过代码实现环状队列?

之前说到,C# 中有个现成的类实现了队列就是Queue这个类。但是并没有现成的环状队列。

要手动实现环形缓冲队列(Circular Buffer)在 C# 中,可以通过结合 Queue<T> 或者直接使用一个固定大小的数组来模拟环形队列的行为。下面是两种常见的实现方式。

1. 使用 Queue<T> 实现环形缓冲队列

虽然 Queue<T> 本身并不是环形队列,但我们可以通过管理队列的最大容量和覆盖旧数据来模拟环形缓冲队列的行为。当队列满时,新的数据会覆盖最旧的数据。

public class CircularQueue<T>
{private readonly Queue<T> queue;private readonly int capacity;public CircularQueue(int capacity){this.capacity = capacity;this.queue = new Queue<T>(capacity);}// 添加元素,如果队列已满,则移除最旧的元素public void Enqueue(T item){if (queue.Count == capacity){queue.Dequeue(); // 移除最旧的元素}queue.Enqueue(item);}// 从队列中取出元素public T Dequeue(){if (queue.Count == 0){throw new InvalidOperationException("Queue is empty.");}return queue.Dequeue();}// 查看队列中的第一个元素public T Peek(){if (queue.Count == 0){throw new InvalidOperationException("Queue is empty.");}return queue.Peek();}// 判断队列是否为空public bool IsEmpty() => queue.Count == 0;// 队列中的元素个数public int Count => queue.Count;
}

使用示例:

CircularQueue<int> circularQueue = new CircularQueue<int>(3);circularQueue.Enqueue(1);
circularQueue.Enqueue(2);
circularQueue.Enqueue(3);Console.WriteLine(circularQueue.Dequeue()); // 输出 1
circularQueue.Enqueue(4); // 现在队列已满,1 会被覆盖Console.WriteLine(circularQueue.Dequeue()); // 输出 2
Console.WriteLine(circularQueue.Dequeue()); // 输出 3
Console.WriteLine(circularQueue.Dequeue()); // 输出 4

说明:

  • Queue<T> 用于存储数据,最大容量为 capacity
  • 当队列满时(元素数量等于 capacity),通过 Dequeue() 移除最旧的元素,再插入新的元素,模拟环形缓冲的行为。

这种方式依赖于 Queue<T> 来管理队列的基本操作,简单易懂,但不能完全利用环形缓冲队列的内存高效性,尤其是在每次扩展队列容量时仍会引起内存分配。


2. 使用固定大小数组实现环形缓冲队列

这种方法通过手动管理队列的头尾指针和数组来实现环形缓冲区,避免了 Queue<T> 的扩展和额外的内存分配。下面是一个更低层次的实现方式:

public class CircularBuffer<T>
{private readonly T[] buffer;private int head;private int tail;private int size;private readonly int capacity;public CircularBuffer(int capacity){this.capacity = capacity;this.buffer = new T[capacity];this.head = 0;this.tail = 0;this.size = 0;}// 添加元素到队列public void Enqueue(T item){if (size == capacity){// 队列已满,覆盖最旧的数据head = (head + 1) % capacity; // 更新头指针}else{size++;}buffer[tail] = item;tail = (tail + 1) % capacity; // 更新尾指针}// 从队列中取出元素public T Dequeue(){if (size == 0){throw new InvalidOperationException("Queue is empty.");}T value = buffer[head];head = (head + 1) % capacity; // 更新头指针size--;return value;}// 查看队列的第一个元素public T Peek(){if (size == 0){throw new InvalidOperationException("Queue is empty.");}return buffer[head];}// 判断队列是否为空public bool IsEmpty() => size == 0;// 队列中的元素个数public int Count => size;
}

使用示例:

CircularBuffer<int> buffer = new CircularBuffer<int>(3);buffer.Enqueue(1);
buffer.Enqueue(2);
buffer.Enqueue(3);Console.WriteLine(buffer.Dequeue()); // 输出 1
buffer.Enqueue(4); // 1 被覆盖Console.WriteLine(buffer.Dequeue()); // 输出 2
Console.WriteLine(buffer.Dequeue()); // 输出 3
Console.WriteLine(buffer.Dequeue()); // 输出 4

说明:

  • 通过一个固定大小的数组 buffer 存储数据,队列大小为 capacity
  • headtail 指针管理数据的入队和出队。head 指针指向队列的头部(最旧的元素),tail 指针指向队列的尾部(最新的元素)。
  • 当队列满时,新元素会覆盖最旧的数据,head 指针会移动到下一个位置,从而实现环形缓冲队列的覆盖行为。

这种方式比 Queue<T> 更高效,避免了额外的内存分配,适合需要频繁进行入队和出队操作的场景。


小结

  • 使用 Queue<T>:可以通过在队列满时删除最旧元素来模拟环形缓冲队列,适用于简单的场景。
  • 使用固定大小数组:手动管理头尾指针和队列大小,更高效,避免内存分配,适用于性能要求较高的场景。

队列和环状队列的对比


1. 环形缓冲队列是FIFO的一种实现

  • FIFO原则:数据按照到达顺序处理,先进入队列的数据先被取出。
  • 环形缓冲队列:通过固定大小的数组和循环指针实现FIFO,满足先进先出的特性。

2. 环形缓冲队列的特点

  • 固定大小:预分配固定容量的内存,空间利用率高。
  • 循环利用:通过头尾指针循环移动,重复利用数组空间。
  • 高效性能:插入和删除操作的时间复杂度都是O(1)。
  • 内存紧凑:数据连续存储,缓存友好。

3. 环形缓冲队列 vs 其他FIFO实现

特性环形缓冲队列链表实现的FIFO动态数组实现的FIFO
内存分配一次性预分配动态分配节点动态扩容
空间利用率100%较低(每个节点有额外开销)较高(但有扩容开销)
插入/删除性能O(1)O(1)均摊O(1),扩容时O(n)
随机访问不支持不支持支持
适用场景固定大小数据流、实时系统数据量变化大、简单实现需要随机访问的场景

4. 环形缓冲队列的局限性

  • 固定大小:需要预先确定容量,不适合数据量变化大的场景。
  • 不支持随机访问:只能按顺序访问数据。
  • 溢出处理:队列满时需要明确策略(覆盖旧数据或报错)。

5. 小结

  • 环形缓冲队列是FIFO的一种高效实现,特别适合固定大小、高吞吐量的场景。
  • 它通过循环利用预分配的内存,避免了动态内存分配的开销,同时保持了FIFO的特性。
  • 如果需要动态扩容或更灵活的内存管理,可以选择其他FIFO实现(如链表或动态数组)。

线程安全问题


1 多线程访问队列的潜在问题
1.1 竞态条件(Race Condition)
问题描述:多个线程同时修改队列的状态(如 head 和 tail 指针),导致数据不一致。

示例:
线程A和线程B同时执行入队操作。
两者读取相同的 head 指针值,导致数据覆盖或丢失。

1.2 数据不一致
问题描述:一个线程正在修改队列,另一个线程同时读取队列,导致读取到不完整或错误的数据。

示例:

线程A正在入队,更新了 head 指针但还未写入数据。

线程B读取 head 指针,误认为新数据已写入。

1.3 死锁(Deadlock)
问题描述:多个线程互相等待对方释放锁,导致程序无法继续执行。

示例:

线程A持有锁1并等待锁2。

线程B持有锁2并等待锁1。

Queue 如果一个线程只负责写,一个线程只负责读会有问题吗?

如果一个线程 只负责写Enqueue)而另一个线程 只负责读Dequeue),在 不使用锁 或其他线程同步机制的情况下,Queue<T> 仍然 可能会遇到问题,即使你不打算在同一时间内进行读写操作。

问题原因:

  • 队列的内部状态Queue<T> 并没有内建的线程安全机制来保证即使在读写操作不重叠的情况下,两个线程对队列的访问是安全的。
    • 例如,读线程可能会在 写线程 操作队列时,导致内部数据不一致或访问冲突。即使一个线程只负责写,另一个线程只负责读,也可能会出现 竞态条件(race condition)或 内存可见性问题

一些潜在的风险:

  1. 队列大小(Count)的读取:如果 Queue<T> 正在被修改(例如,写线程在 Enqueue),另一个线程试图读取队列大小或进行 Dequeue 操作,可能会得到不一致的结果。因为写线程可能在修改队列时,读线程同时查看到一个不完全或不一致的队列状态。

  2. 数据一致性:尽管读写操作看似是顺序执行的,实际上在多个线程访问共享数据时,现代 CPU 和优化可能导致线程看到过时或不一致的数据(内存可见性问题)。因此,即使操作本身是序列化的,底层的硬件优化仍可能引发问题。

如何解决?

1. 使用锁 (lock)

通过使用 lock 确保 写操作读操作 不会同时进行,这样可以防止数据竞争和不一致性:

public class ThreadSafeQueue<T>
{private readonly Queue<T> queue = new Queue<T>();private readonly object lockObject = new object();public void Enqueue(T item){lock (lockObject){queue.Enqueue(item);}}public T Dequeue(){lock (lockObject){if (queue.Count == 0)throw new InvalidOperationException("Queue is empty.");return queue.Dequeue();}}public int Count{get{lock (lockObject){return queue.Count;}}}
}

在这个示例中,通过 lock 来确保写操作和读操作不会发生竞态条件。

2. 使用 ConcurrentQueue<T>

如果你不希望手动加锁,可以使用 ConcurrentQueue<T>,它是线程安全的,可以在多个线程中同时进行读写操作,保证数据的一致性和正确性:

using System.Collections.Concurrent;var concurrentQueue = new ConcurrentQueue<int>();// 写线程:入队
concurrentQueue.Enqueue(1);
concurrentQueue.Enqueue(2);// 读线程:出队
if (concurrentQueue.TryDequeue(out int result))
{Console.WriteLine(result); // 安全地获取队列元素
}

ConcurrentQueue<T> 会自动管理线程同步,因此你不需要担心加锁的问题,它会确保多线程环境下的正确性。

总结:

  • 即使一个线程只负责写,另一个线程只负责读,Queue<T> 仍然 不保证线程安全,会有潜在的竞态条件和数据不一致问题。
  • 如果需要确保线程安全,可以使用 lock 来同步读写操作,或者使用 ConcurrentQueue<T> 来避免手动管理同步。推荐使用 ConcurrentQueue<T>,因为它是专为多线程设计并且已经实现了高效的线程安全。

相关文章:

【C# 数据结构】队列 FIFO

目录 队列的概念FIFO (First-In, First-Out)Queue<T> 的工作原理&#xff1a;示例&#xff1a;解释&#xff1a; 小结&#xff1a; 环形队列1. **FIFO&#xff1f;**2. **环形缓冲队列如何实现FIFO&#xff1f;**关键概念&#xff1a; 3. **环形缓冲队列的工作过程**假设…...

git 克隆及拉取github项目到本地微信开发者工具,微信开发者工具通过git commit、git push上传代码到github仓库

git 克隆及拉取github项目到本地微信开发者工具&#xff0c;微信开发者工具通过git commit、git push上传代码到github仓库 git 克隆及拉取github项目到本地 先在自己的用户文件夹新建一个项目文件夹&#xff0c;取名为项目名 例如这样 C:\Users\HP\yzj-再打开一个终端页面&…...

【机器学习】多元线性回归算法和正规方程解求解

多元线性方差和正规方差解 一、摘要二、多元线性回归介绍三、正规方程解的求解及代码实现 一、摘要 本文围绕多元线性回归的正规方程解展开&#xff0c;为初学者系统介绍了相关基本概念、求解方法、实际应用以及算法封装要点。 首先&#xff0c;深入阐释了正规方程解这一多元…...

在Linux上创建一个Docker容器并在其中执行Python脚本

在Linux上创建一个Docker容器并在其中执行Python脚本的过程&#xff0c;涉及多个方面的内容&#xff0c;包括安装Docker、编写Dockerfile、构建镜像、运行容器等。 1. 安装Docker 在Linux上使用Docker之前&#xff0c;你需要确保系统已安装Docker。Docker支持的Linux发行版有…...

Linux C 静态库如何生成并使用

1. 编写源文件 首先创建一个简单的示例项目&#xff0c;包含一个头文件和一个源文件。 头文件 my_lib.h // my_lib.h #ifndef MY_LIB_H #define MY_LIB_H// 函数声明 int add(int a, int b);#endif 源文件 my_lib.c #include <stdio.h>void print_hello() {printf(&q…...

清华大学deepseek教程第四版 DeepSeek+DeepResearch 让科研像聊天一样简单(附下载)

deepseek使用教程系列 DeepSeekDeepResearch 让科研像聊天一样简单(附下载) https://pan.baidu.com/s/1VMgRmCSEzNvhLZQc8mu6iQ?pwd1234 提取码: 1234 或 https://pan.quark.cn/s/f3d4511b790a...

请解释 Vue 中的生命周期钩子,不同阶段触发的钩子函数及其用途是什么?

vue生命周期钩子详解&#xff08;Vue 3版本&#xff09; 一、生命周期阶段划分 Vue组件的生命周期可分为四大阶段&#xff0c;每个阶段对应特定钩子函数&#xff1a; 创建阶段&#xff1a;初始化实例并准备数据挂载阶段&#xff1a;将虚拟DOM渲染为真实DOM更新阶段&#xff…...

输入搜索、分组展示选项、下拉选取,el-select 实现:即输入关键字检索,返回分组选项,选取跳转到相应内容页 —— VUE 项目-全局模糊检索

后端数据代码写于下一篇&#xff1a;输入搜索、分组展示选项、下拉选取&#xff0c;全局跳转页&#xff0c;el-select 实现 —— 后端数据处理代码&#xff0c;抛砖引玉展思路 【效果图】&#xff1a;分组展示选项 【去界面操作感受一下】—> 便捷简洁的企业官网 【录制效…...

Transformer为什么需要多头注意力(Multi-Head Attention)?如果没有多头会怎么样?

直接回答 关键点&#xff1a; Transformer 中的多头注意力&#xff08;Multi-Head Attention&#xff09;允许模型同时关注输入数据的不同方面&#xff0c;提升性能。 如果没有多头&#xff0c;模型可能无法捕捉复杂关系&#xff0c;表现会下降。 什么是多头注意力&#xff…...

VUE中的组件加载方式

加载方式有哪些&#xff0c;及如何进行选择 常规的静态引入是在组件初始化时就加载所有依赖的组件&#xff0c;而懒加载则是等到组件需要被渲染的时候才加载。 对于大型应用&#xff0c;可能会有很多组件&#xff0c;如果一开始都加载&#xff0c;可能会影响首屏加载时间。如…...

Linux自启动fastapi服务

步骤一 在/etc/systemd/system/文件夹下创建pyod.service&#xff08;其中/path/to/conda/bin/activate要改为activate实际存放位置&#xff0c;例如miniconda的实际存放位置为/root/miniconda3/bin/activate&#xff09; [Unit] DescriptionPyOD Uvicorn Service Afternetwo…...

C++与Python:两种编程语言的区别

C和Python都是当今编程领域广泛使用的语言&#xff0c;它们各有特色&#xff0c;适用于不同的开发场景。本文将从语言特性、性能、学习难度、应用领域等多个方面探讨C与Python之间的区别。 一、语言特性 类型系统&#xff1a; C&#xff1a;是一种静态类型语言&#xf…...

进程线程的创建、退出、回收

1. 进程相关知识点 1.1 进程创建 fork()&#xff1a; 功能&#xff1a;创建一个子进程。 返回值&#xff1a; 父进程中返回子进程的 PID。 子进程中返回 0。 失败返回 -1。 特点&#xff1a;子进程是父进程的副本&#xff0c;拥有独立的内存空间。 vfork()&#xff1a;…...

深度学习-6.用于计算机视觉的深度学习

Deep Learning - Lecture 6 Deep Learning for Computer Vision 简介深度学习在计算机视觉领域的发展时间线 语义分割语义分割系统的类型上采样层语义分割的 SegNet 架构软件中的SegNet 架构数据标注 目标检测与识别目标检测与识别问题两阶段和一阶段目标检测与识别两阶段检测器…...

低概率发生调用`pthread_cond_wait`的线程没有被唤醒

低概率发生调用pthread_cond_wait的线程没有被唤醒 背景&#xff1a; 你是否也踩过坑&#xff0c;在A线程调用pthread_cond_wait等待&#xff0c;在B线程调用pthread_cond_signal唤醒A线程进行工作处理&#xff0c;然后在某一次用户产品反馈中发现了低概率问题。A线程像是卡住…...

MATLAB学习之旅:数据插值与曲线拟合

在MATLAB的奇妙世界里,我们已经走过了一段又一段的学习旅程。从基础的语法和数据处理,到如今,我们即将踏入数据插值与曲线拟合这片充满魅力的领域。这个领域就像是魔法中的艺术创作,能够让我们根据现有的数据点,构建出更加丰富的曲线和曲面,从而更好地理解和描述数据背后…...

Python复习

第一章 Python概述 python特点 优点&#xff1a; 简单易学&#xff1b;开发效率高&#xff1b;典型的工具语言&#xff1b;强大丰富的模块库&#xff1b;优秀的跨平台&#xff1b; 缺点&#xff1a; 执行效率不高&#xff1b;代码不能加密&#xff1b;用缩进区分语句关系&…...

通信系统中物理层与网络层联系与区别

在通信系统中&#xff0c;物理层和网络层是OSI&#xff08;开放系统互连&#xff09;模型中的两个重要层次&#xff0c;分别位于协议栈的最底层和第三层。它们在功能、职责和实现方式上有显著的区别&#xff0c;但同时也在某些方面存在联系。以下是物理层与网络层的联系与区别的…...

go 错误处理 error

普通错误处理 // 包路径 package mainimport ("errors""fmt" )func sqrt(f1, f2 float64) (float64, error) {if f2 < 0 {return 0, errors.New("error: f2 < 0")}return f1 / f2, nil }func sqrt1(f1, f2 float64) {if re, err : sqrt(f…...

Redis 缓存穿透、击穿、雪崩:问题与解决方案

在使用 Redis 作为缓存中间件时&#xff0c;系统可能会面临一些常见的问题&#xff0c;如 缓存穿透、缓存击穿 和 缓存雪崩。这些问题如果不加以解决&#xff0c;可能会导致数据库压力过大、系统响应变慢甚至崩溃。本文将详细分析这三种问题的起因&#xff0c;并提供有效的解决…...

Spring容器初始化扩展点:ApplicationContextInitializer

目录 一、什么是ApplicationContextInitializer&#xff1f; 1、核心作用2、适用场景 二、ApplicationContextInitializer的使用方式 1、实现ApplicationContextInitializer接口2、注册初始化器 三、ApplicationContextInitializer的执行时机四、实际应用案例 1、动态设置环境…...

冯·诺依曼体系结构、理解操作系统管理

在谈操作系统概念之前&#xff0c;先简单讲解一下冯诺伊曼体系结构&#xff0c;理解了在硬件层面上数据流的走向&#xff0c;这对后续的理解有很大的帮助。 文章目录 一.冯诺依曼结构冯诺依曼体系结构内存存在的意义 二.理解操作系统管理操作系统的作用管理的本质系统调用 一.…...

Linux初体验:从零开始掌握操作系统的发展与多样性

Linux初体验&#xff1a;从零开始掌握操作系统的发展与多样性 前言一、什么是Linux&#xff1f;1. Linux的定义2. Linux的组成 二、Linux的发展历史1. Unix的诞生2. Linux的诞生3. Linux的普及 三、Linux的发行版1. **Ubuntu**2. **CentOS**3. **Debian**4. **Fedora**5. **Arc…...

文心一言大模型的“三级跳”:从收费到免费再到开源,一场AI生态的重构实验

2025年2月&#xff0c;百度文心大模型接连抛出两枚“重磅炸弹”&#xff1a;4月1日起全面免费&#xff0c;6月30日正式开源文心大模型4.5系列。这一系列动作不仅颠覆了李彦宏此前坚持的“闭源优势论”13&#xff0c;更标志着中国AI大模型竞争进入了一个全新的阶段——从技术壁垒…...

技术教程 | 如何实现1v1音视频通话(含源码)

今天&#xff0c;给大家讲一下怎么实现1v1音视频通话&#xff0c;以下是教程内容&#xff1a; 开发环境 开发环境要求如下&#xff1a; 环境要求说明JDK 版本1.8.0 及以上版本Android API 版本API 21、Android Studio 5.0 及以上版本CPU架构ARM 64、ARMV7IDEAndroid Studio其…...

mysql实时同步到es

测试了多个方案同步&#xff0c;最终选择oceanu产品&#xff0c;底层基于Flink cdc 1、实时性能够保证&#xff0c;binlog量很大时也不产生延迟 2、配置SQL即可完成&#xff0c;操作上简单 下面示例mysql的100张分表实时同步到es&#xff0c;优化备注等文本字段的like查询 创…...

Linux-ubuntu系统移植之Uboot启动流程

Linux-ubuntu系统移植之Uboot启动流程 一&#xff0c;Uboot启动流程1.Uboot的两阶段1.1.第一阶段1.11.硬件初始化1.12.复制 U-Boot 到 RAM1.13.跳转到第二阶段 1.2.第二阶段1.21.C 语言环境初始化1.22. 硬件设备初始化1.23. 加载环境变量1.24. 显示启动信息1.25. 等待用户输入&…...

《Operating System Concepts》阅读笔记:p62-p75

《Operating System Concepts》学习第 10 天&#xff0c;p62-p75 总结&#xff0c;总计 14 页。 一、技术总结 1. system call (1) 定义 The primary interface between processes and the operating system, providing a means to invoke services made available by th…...

【Java场景题】MySQL死锁排查

大家好&#xff0c;今天XiXi给大家分享一个MySQL死锁排查的实验&#xff0c;文章主要有&#xff1a; 通过show engine innodb status&#xff0c;查看最近一次死锁信息开启innodb_print_all_deadlocks&#xff0c;在错误日志中能够记录所有死锁信息通过解析binlog日志定位死锁…...

JSON格式,C语言自己实现,以及直接调用库函数(一)

JSON&#xff08;JavaScript Object Notation&#xff09;是一种轻量级的数据交换格式&#xff0c;易于人阅读和编写&#xff0c;同时也易于机器解析和生成。以下为你提供不同场景下常见的 JSON 格式示例。 1. 简单对象 JSON 对象是由键值对组成&#xff0c;用花括号 {} 包裹&…...

leetcode刷题第十三天——二叉树Ⅲ

本次刷题顺序是按照卡尔的代码随想录中给出的顺序 翻转二叉树 226. 翻转二叉树 /*** Definition for a binary tree node.* struct TreeNode {* int val;* struct TreeNode *left;* struct TreeNode *right;* };*//*总体思路就是&#xff0c;对于每一个结点&…...

spring boot知识点5

1.如何你有俩套配置环境&#xff0c;运行时如何选择 如果有俩套配置环境&#xff0c;则需要三个yml application.yml 用于配置你用那个配置环境 application-dev.yml 用于开发配置环境 application-prod.yml 用于发布配置环境 spring:profiles:active: prod # 指定当前激…...

bboss v7.3.5来袭!新增异地灾备机制和Kerberos认证机制,助力企业数据安全

ETL & 流批一体化框架 bboss v7.3.5 发布&#xff0c;多源输出插件增加为特定输出插件设置记录过滤功能&#xff1b;Elasticsearch 客户端新增异地双中心灾备机制&#xff0c;提升框架高可用性&#xff1b;Elasticsearch client 和 http 微服务框架增加对 Kerberos 认证支持…...

Android自带的省电模式主要做什么呢?

Android自带的省电模式主要做什么呢&#xff1f; 省电模式支持的策略 LOCATION 灭屏后开启GPS待机省电模式 VIBRATION 关闭触摸震动和来电震动 ANIMATION 关闭动画 FULL_BACKUP 全备份 KEYVALUE_BACKUP 键值备份 NETWORK_FIREWALL 网络防火墙&#xff0c;限制 Doze …...

tp6上传文件大小超过了最大值+验证文件上传大小和格式函数

问题&#xff1a; 最近用tp6的文件上传方法上传文件时报文件过大错误。如下所示&#xff1a; $file $this->request->file(file);{"code": 1,"msg": "上传文件大小超过了最大值&#xff01;","data": {"code": 1,&q…...

将RocketMQ集成到了Spring Boot项目中,实现站内信功能

1. 添加依赖 首先&#xff0c;在pom.xml中添加RocketMQ的依赖&#xff1a; <dependencies><!-- Spring Boot Starter Web --><dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-web</artifac…...

Spring Boot文件上传

5.3.1文件上传 开发Web应用时&#xff0c;文件上传是很常见的一个需求浏览器通过表单形式将文件以流的形式传递给服务器&#xff0c;服务器再对上传的数据解析处理。下面我们通过一个案例讲解如何使用SpringBoot实现文件上传&#xff0c;具体步骤如下。 1.编写文件上传的表单…...

动态规划算法

动态规划算法模板 public class DynamicProgramming {public int solve(int n, int[] nums) {// Step 1: 初始化 dp 数组&#xff0c;dp[i] 表示从0到i的最优解int[] dp new int[n 1]; // Step 2: 设置初始条件&#xff0c;通常是dp数组的第一个元素dp[0] 0; // 假设从第0个…...

Python中常见库 PyTorch和Pydantic 讲解

PyTorch 简介 PyTorch 是一个开源的深度学习框架&#xff0c;由 Facebook 的 AI 研究团队开发。它提供了丰富的工具和库&#xff0c;用于构建和训练各种深度学习模型&#xff0c;如卷积神经网络&#xff08;CNN&#xff09;、循环神经网络&#xff08;RNN&#xff09;及其变体&…...

74. 搜索二维矩阵(LeetCode 热题 100)

题目来源; 74. 搜索二维矩阵 - 力扣&#xff08;LeetCode&#xff09; 题目内容&#xff1a; 给你一个满足下述两条属性的 m x n 整数矩阵&#xff1a; 每行中的整数从左到右按非严格递增顺序排列。 每行的第一个整数大于前一行的最后一个整数。 给你一个整数 target &am…...

高防服务器的适用场景有哪些?

高防服务器作为具有着较高防御能力的网络设备&#xff0c;可以抵御DDOS和CC等常见的网络攻击类型&#xff0c;保障企业服务的连续性和稳定性&#xff0c;那高防服务器的适用场景有哪些呢&#xff1f; 对于大型的网站和电商平台来说&#xff0c;高流量的用户访问和数据信息让它们…...

HTTP与网络安全

一、HTTPS和HTTP有怎样的区别呢&#xff1f;HTTPS HTTP SSL/TLS&#xff08;SSL或者TLS&#xff09; HTTP&#xff1a;应用层 SSL/TLS&#xff1a;协议中间层 TCP&#xff1a;传输层 IP&#xff1a;网络层 HTTPS 是安全的HTTP&#xff0c;他的安全是由SSL或者TLS来决定的&a…...

UE地编材质世界对齐纹理旋转

帖子地址 https://forums.unrealengine.com/t/how-to-rotate-a-world-aligned-texture/32532/4世界对齐纹理本身不能改 自己创建了个函数 把世界对齐纹理的内容赋值粘贴 在纹理偏移里给值 不要局限0-1 给值给大一点...

SpringBoot使用Nacos进行application.yml配置管理

Nacos是阿里巴巴开源的一个微服务配置管理和服务发现的解决方案。它提供了动态服务发现、配置管理和 服务管理平台。Nacos的核心功能包括服务发现、配置管理和动态服务管理&#xff0c;使得微服务架构下的服务治理 变得简单高效。 Nacos的设计基于服务注册与发现、配置管理、动…...

JavaScript中的symbol类型的意义和使用

JavaScript 中的Symbol类型是 ES6&#xff08;ECMAScript 2015&#xff09;引入的一种原始数据类型&#xff0c;它表示独一无二的值。下面详细介绍 Symbol 的意义和使用方法。 意义 1. 避免属性名冲突 在 JavaScript 中&#xff0c;对象的属性名通常是字符串。当多个模块或者…...

C++ 设计模式-状态模式

火箭状态模式,涵盖发射、多级分离、入轨、返航、紧急状态等流程,以及状态间的转换逻辑: 状态设计 状态列表: IdleState(待机)PreparingState(准备)LaunchingState(发射中)FirstStageSeparatingState(一级分离)SecondStageSeparatingState(二级分离)ThirdStageSep…...

verilog基础知识

一,Verilog和VHDL区别 全世界高层次数字系统设计领域中,应用Verilog和VHDL的比率是80%和20%;这两种语言都是用于数字电路系统设计的硬件描述语言, 而且都已经是 IEEE 的标准。 VHDL 是美国军方组织开发的,VHDL1987年成为标准;Verilog 是由一个公司的私有财产转化而来,…...

14.8 Auto-GPT 自主智能体设计解密:构建具备长期记忆的智能决策系统

Auto-GPT 自主智能体设计解密:构建具备长期记忆的智能决策系统 关键词:Auto-GPT 架构设计、自主智能体开发、LangChain Agents、长期记忆系统、工具链编排 1. 自主智能体的核心架构设计 Auto-GPT 系统架构图解: #mermaid-svg-NuDU1eo6sXqhA6Ve {font-family:"trebuch…...

ubuntu安装docker docker/DockerHub 国内镜像源/加速列表【持续更新】

ubuntu安装docker & docker镜像代理【持续更新】 在Ubuntu上安装Docker&#xff0c;你可以选择两种主要方法&#xff1a;从Ubuntu的仓库安装&#xff0c;或者使用Docker的官方仓库安装。下面我会详细解释这两种方法。 方法一&#xff1a;从Ubuntu的仓库安装Docker 这种方…...

模拟实现分布式文件存储

Q1:如何解决海量数据存的下的问题 传统做法是在单机存储。但是随着数据变多&#xff0c;会遇到存储瓶颈。 单机纵向扩展&#xff1a;内存不够加内存&#xff0c;磁盘不够加磁盘。有上限限制&#xff0c;不能无限制加下去。 多机横向扩展&#xff1a;采用多台机器存储&#x…...