新增线程安全定长队列
This commit is contained in:
parent
074fe08e5f
commit
08c5e7e8b8
60
Falcon.SugarApi.Test/ThreadSafeFixedSizeQueueTest.cs
Normal file
60
Falcon.SugarApi.Test/ThreadSafeFixedSizeQueueTest.cs
Normal 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);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
123
Falcon.SugarApi/ThreadSafeFixedSizeQueue.cs
Normal file
123
Falcon.SugarApi/ThreadSafeFixedSizeQueue.cs
Normal 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;
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
Loading…
Reference in New Issue
Block a user