新增线程安全定长队列

This commit is contained in:
Falcon 2025-04-23 14:51:57 +08:00
parent 074fe08e5f
commit 08c5e7e8b8
2 changed files with 183 additions and 0 deletions

View File

@ -0,0 +1,60 @@
using Microsoft.VisualStudio.TestTools.UnitTesting;
namespace Falcon.SugarApi.Test
{
/// <summary>
/// 任务防抖测试
/// </summary>
[TestClass()]
public class ThreadSafeFixedSizeQueueTest
{
/// <summary>
/// 出入数据测试
/// </summary>
[TestMethod()]
public void TestInOut() {
var queue = new ThreadSafeFixedSizeQueue<int>(3);
var i = queue.Dequeue();
Assert.IsTrue(i == 0);
queue.Enqueue(1);
Assert.IsTrue(queue.Count == 1);
i = queue.Dequeue();
Assert.IsTrue(i == 1);
queue.Enqueue(1);
queue.Enqueue(2);
queue.Enqueue(3);
queue.Enqueue(4);
queue.Enqueue(5);
Assert.IsTrue(queue.Count == 3);
i = queue.Dequeue();
Assert.IsTrue(i == 3);
i = queue.Dequeue();
Assert.IsTrue(i == 4);
i = queue.Dequeue();
Assert.IsTrue(i == 5);
Assert.IsTrue(queue.Count == 0);
queue.Enqueue(1);
queue.Enqueue(2);
queue.Enqueue(3);
queue.Clear();
Assert.IsTrue(queue.Count == 0);
i = queue.Dequeue();
Assert.IsTrue(i == 0);
queue.Enqueue(1);
queue.Enqueue(2);
queue.Enqueue(3);
int id = 1;
while(queue.TryDequeue(out i)) {
Assert.IsTrue(i == id++);
}
Assert.IsTrue(queue.Count == 0);
}
}
}

View File

@ -0,0 +1,123 @@
using System;
namespace Falcon.SugarApi
{
/// <summary>
/// 线程安全的固定长度先入先出队列
/// </summary>
/// <typeparam name="T"></typeparam>
public class ThreadSafeFixedSizeQueue<T>
{
private readonly T[] _buffer;
/// <summary>
/// 最新添加的元素
/// </summary>
private int _head;
/// <summary>
/// 最早加入的元素
/// </summary>
private int _tail;
/// <summary>
/// 当前元素数量
/// </summary>
public int Count { get; private set; }
/// <summary>
/// 线程安全锁
/// </summary>
private readonly object _lock = new object();
/// <summary>
/// 元素数量
/// </summary>
public int Capacity { get; private set; }
/// <summary>
/// 通过指定元素数量实例化固定长度的线程安全队列
/// </summary>
/// <param name="capacity">队列长度</param>
/// <exception cref="ArgumentException">参数异常</exception>
public ThreadSafeFixedSizeQueue(int capacity) {
if(capacity <= 0)
throw new ArgumentException("Capacit只能是正整数",nameof(capacity));
Capacity = capacity;
_buffer = new T[capacity];
_head = 0;
_tail = 0;
this.Count = 0;
}
/// <summary>
/// 添加元素到队列,队列满时自动覆盖最早加入的元素
/// </summary>
public void Enqueue(T item) {
lock(_lock) {
if(this.Count == 0) {
_head = 0;
_tail = 0;
this.Count = 1;
_buffer[0] = item;
return;
}
if(this.Count == this.Capacity) {
headMoveNext();
tailMoveNext();
_buffer[_head] = item;
return;
}
headMoveNext();
this.Count++;
this._buffer[_head] = item;
}
}
/// <summary>
/// 移除并返回队列尾部的元素
/// </summary>
public T? Dequeue() {
if(this.Count == 0)
return default;
lock(_lock) {
T item = _buffer[this._tail];
tailMoveNext();
this.Count--;
return item;
}
}
/// <summary>
/// 尝试获取队列尾部元素
/// </summary>
/// <param name="item"></param>
/// <returns></returns>
public bool TryDequeue(out T? item) {
if(Count == 0) {
item = default;
return false;
}
lock(_lock) {
item = _buffer[_tail];
Count--;
tailMoveNext();
return true;
}
}
/// <summary>
/// 清除队列内元素
/// </summary>
public void Clear() {
lock(_lock) {
_head = 0;
_tail = 0;
Count = 0;
}
}
/// <summary>
/// 头位置移至下一位
/// </summary>
private int headMoveNext() => _head = (_head + 1) % Capacity;
/// <summary>
/// 尾位置头位置移至下一位
/// </summary>
private int tailMoveNext() => _tail = (_tail + 1) % Capacity;
}
}