新增线程安全定长队列
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