直接上代码
using System;
using System.Collections.Concurrent;
using System.Collections.Generic;
using System.Diagnostics;
using System.Threading;
using System.Threading.Tasks.Dataflow;
namespace ConsoleApp1.Threading
{
public class ThreadingTest
{
const int ThreadingCount = 100;
int _total = 0;
readonly Random _random;
readonly Stopwatch _watch;
/// <summary>
/// 处理中的数据量
/// </summary>
readonly ConcurrentDictionary<long, HandlerDetail> _memberHandlerDetailDic;
/// <summary>
/// 输出方便显示用
/// </summary>
readonly ConcurrentDictionary<string, List<string>> _writeLineDic;
/// <summary>
/// 业务队列
/// <para>item1业务ID item2自己处理的顺序 item3任务信息</para>
/// </summary>
ActionBlock<Tuple<long, int, string>> _actionBlock;
public ThreadingTest()
{
_random = new Random();
_watch = new Stopwatch();
_memberHandlerDetailDic = new ConcurrentDictionary<long, HandlerDetail>();
_writeLineDic = new ConcurrentDictionary<string, List<string>>();
_actionBlock = new ActionBlock<Tuple<long, int, string>>(Handler, new ExecutionDataflowBlockOptions { MaxDegreeOfParallelism = ThreadingCount });
}
public void Main()
{
_watch.Start();
var taskCount = 5000;
for (int i = 0; i < taskCount; i++)
{
Consume(new Tuple<long, string>(_random.Next(1, ThreadingCount + 10), $"Task序号{i:000000}"));
}
var totalTime = _watch.Elapsed.TotalMilliseconds;
Console.WriteLine($"============入队完成");
// 等待完成
SpinWait.SpinUntil(() => _total >= taskCount);
// 打印
foreach (var dic in _writeLineDic)
{
foreach (var item in dic.Value)
{
Console.WriteLine($"{dic.Key}{item}");
}
Console.WriteLine();
}
var totalHandleTime = _watch.Elapsed.TotalMilliseconds;
Console.WriteLine($"============处理时间统计:{totalHandleTime}ms");
Console.WriteLine($"============入队时间统计:{totalTime}ms");
Console.WriteLine($"============处理完成数量:{_total}");
}
/// <summary>
/// 消费
/// </summary>
private void Consume(Tuple<long, string> tuple)
{
var cur = ModifyHandlerDetail(tuple.Item1, 1);
RemoveMemberHandlerDetailDic();
// 入队解耦
_actionBlock.Post(new Tuple<long, int, string>(tuple.Item1, cur, tuple.Item2));
}
/// <summary>
/// 定时清理列表
/// </summary>
private void RemoveMemberHandlerDetailDic()
{
if (DateTime.Now.Minute % 30 == 1)
{
var removeList = new List<long>();
foreach (var item in _memberHandlerDetailDic)
{
if (item.Value.Outstanding == 0) removeList.Add(item.Key);
}
foreach (var key in removeList)
{
_memberHandlerDetailDic.TryRemove(key, out _);
}
}
}
/// <summary>
/// 业务处理
/// </summary>
/// <param name="tuple"></param>
private void Handler(Tuple<long, int, string> tuple)
{
var startTime = $"{DateTime.Now:HH:mm:ss fff}";
var startWait = _watch.Elapsed.TotalMilliseconds;
// 等待
SpinWait.SpinUntil(() => tuple.Item2 - _memberHandlerDetailDic[tuple.Item1].Completions == 1);
var endWait = _watch.Elapsed.TotalMilliseconds;
try
{
// 随机处理时间
Thread.Sleep(_random.Next(50, 600));
var item1 = $"ID:{tuple.Item1:0000000000}";
var item3 = $" 处理任务:{tuple.Item3} 开始时间:{startTime} 完成时间:{DateTime.Now:HH:mm:ss fff} 等待时间:{endWait - startWait}";
_writeLineDic.AddOrUpdate(item1, new List<string>() { item3 }, (key, value) =>
{
value.Add(item3);
return value;
});
Console.WriteLine($"{item3}");
}
catch (Exception ex)
{
throw;
}
// 统计处理数量
Interlocked.Increment(ref _total);
ModifyHandlerDetail(tuple.Item1, -1);
}
/// <summary>
/// 修改处理中的任务量
/// </summary>
/// <param name="key"></param>
/// <param name="count"></param>
private int ModifyHandlerDetail(long key, int count)
{
var selfCurrent = 1;
_memberHandlerDetailDic.AddOrUpdate(key, new HandlerDetail { Outstanding = 1, Current = 1, Completions = 0 }, (k, value) =>
{
value.Outstanding += count;
if (count < 0)
{
value.Completions += -count;
}
else
{
value.Current += count;
selfCurrent = value.Current;
}
return value;
});
return selfCurrent;
}
}
public class HandlerDetail
{
/// <summary>
/// 未完成数
/// </summary>
public int Outstanding { get; set; }
/// <summary>
/// 当前第N个
/// </summary>
public int Current { get; set; }
/// <summary>
/// 已完成数
/// </summary>
public int Completions { get; set; }
}
}