在實際項目中,需要批量處理一定數量的隊列數據,而不是,一個一個處理,來提高效率。
但是,默認是不支持的。這個時候,就需要這樣的一個業務邏輯對象。
/// <summary>
/// 任務隊列接口
/// </summary>
public interface ITaskQueue<T>
{
/// <summary>
/// 增加一個對象
/// </summary>
/// <param name="t"></param>
void Add(T t);
/// <summary>
/// 獲取一個分組隊列
/// </summary>
/// <returns></returns>
IList<T> GetQueue();
/// <summary>
/// 是否阻塞增加
/// </summary>
/// <returns></returns>
bool IsWaitAdd();
/// <summary>
/// 當前隊列完成
/// </summary>
void Complete();
}
/// <summary>
/// 任務隊列
/// </summary>
public class TaskQueue<T> : ITaskQueue<T>, IDisposable
{
/// <summary>
/// 內置隊列
/// </summary>
private ConcurrentDictionary<int, IList<T>> taskQueues;
/// <summary>
/// 分區大小
/// </summary>
private int PartitionSize;
/// <summary>
/// 默認index爲0
/// </summary>
private int Index = 0;
/// <summary>
/// 默認處理偏移
/// </summary>
private int OffSet = 0;
/// <summary>
/// 內置鎖
/// </summary>
private object Lock = new object();
/// <summary>
/// <summary>
/// 構造
/// </summary>
/// <param name="PartitionSize">分區大小,默認分區大小爲10 </param>
public TaskQueue(int PartitionSize = 10)
{
taskQueues = new ConcurrentDictionary<int, IList<T>>();
this.PartitionSize = PartitionSize;
List<T> ts = new List<T>();
taskQueues.AddOrUpdate(Index, ts, (k, v) => ts);
}
/// <summary>
/// 增加一個對象
/// </summary>
/// <param name="t"></param>
public void Add(T t)
{
lock (Lock)
{
IList<T> ts;
if (taskQueues.TryGetValue(Index, out ts))
{
if (ts.Count < PartitionSize)
{
ts.Add(t);
taskQueues.AddOrUpdate(Index, ts, (k, v) => ts);
}
else //超出區域範圍,則新建區
{
Index++;
IList<T> ts1 = new List<T>();
ts1.Add(t);
taskQueues.AddOrUpdate(Index, ts1, (k, v) => ts1);
}
}
else
{
IList<T> ts1 = new List<T>();
ts1.Add(t);
taskQueues.AddOrUpdate(Index, ts1, (k, v) => ts1);
}
}
}
/// <summary>
/// 獲取一個分組隊列
/// </summary>
/// <returns></returns>
public IList<T> GetQueue()
{
lock (Lock)
{
IList<T> ts;
if (taskQueues.TryGetValue(OffSet, out ts))
{
if (OffSet == Index)//如果直接獲取一個能用的,那就新建區爲新區
{
Index++;
}
return ts;
}
return null;
}
}
/// <summary>
/// 是否阻塞增加
/// </summary>
/// <returns></returns>
public bool IsWaitAdd()
{
lock (Lock)
{
if (OffSet != Index)
{
return true;
}
return false;
}
}
/// <summary>
/// 當前隊列完成
/// </summary>
public void Complete()
{
lock (Lock)
{
IList<T> ts;
taskQueues.TryRemove(OffSet, out ts);
if (OffSet < Index)
{
OffSet++;
}
}
}
public void Dispose()
{
if (taskQueues != null)
{
taskQueues.Clear();
taskQueues = null;
}
}
}
class Program
{
static TaskQueue<string> taskQueue;
static void Main(string[] args)
{
taskQueue = new TaskQueue<string>();
#region 一個一直生產指定大小,另外一個消費 先生產,再消費
//for (int i = 0; i < 1000; i++)
//{
// taskQueue.Add(i.ToString());
//}
////另外一個按照指定的時間,消費
//while (true)
//{
// Thread.Sleep(2000);
// Console.WriteLine("獲取-----開始獲取到數據!");
// var list = taskQueue.GetQueue();
// if (list != null)
// {
// Console.WriteLine($"獲取-----對象狀態:{taskQueue.IsWaitAdd()}已獲取的隊列列表:{string.Join(",", list)}");
// Console.WriteLine("獲取-----處理1秒後,提交當前!");
// Thread.Sleep(1000);
// taskQueue.Complete();
// Console.WriteLine("獲取-----已經提交!");
// }
//}
#endregion
#region 兩個任務處理,實現 一個生產,一個消費 批量 生產,並消費
Task.Run(() =>
{
for (int i = 0; i < 10000000; i++)
{
taskQueue.Add(i.ToString());
Thread.Sleep(100);//一秒插入一條
Console.WriteLine($"插入-----隊列狀態:{taskQueue.IsWaitAdd()}");
while (taskQueue.IsWaitAdd())//有待處理任務
{
Console.WriteLine("插入-----任務插入中開始阻塞!");
SpinWait.SpinUntil(() => !taskQueue.IsWaitAdd());
}
}
});
while (true)
{
Thread.Sleep(2000);
Console.WriteLine("獲取-----開始獲取到數據!");
var list = taskQueue.GetQueue();
if (list != null)
{
Console.WriteLine($"獲取-----對象狀態:{taskQueue.IsWaitAdd()}已獲取的隊列列表:{string.Join(",", list)}");
Console.WriteLine("獲取-----處理10秒後,提交當前!");
Thread.Sleep(1000);
taskQueue.Complete();
Console.WriteLine("獲取-----已經提交!");
}
}
#endregion
Console.WriteLine("開始獲取信息!");
Console.ReadLine();
}
}