介绍开源的.net通信框架NetworkComms框架 源码分析(十五 ) CommsThreadPool自定义线程池
原文网址: http://www.cnblogs.com/csdev
Networkcomms 是一款C# 语言编写的TCP/UDP通信框架 作者是英国人 以前是收费的 目前作者已经开源 许可是:Apache License v2
开源地址是:https://github.com/MarcFletcher/NetworkComms.Net
自定义线程池,用于并发处理通信框架收到的消息
/// <summary> /// A compact priority based thread pool used by NetworkComms.Net to run packet handlers /// 支持优先级处理的自定义线程池 /// </summary> public class CommsThreadPool { /// <summary> /// A sync object to make things thread safe /// 同步锁 /// </summary> object SyncRoot = new object(); /// <summary> /// Dictionary of threads, index is ThreadId /// 线程字典 索引是线程ID /// </summary> Dictionary<int, Thread> threadDict = new Dictionary<int, Thread>(); /// <summary> /// Dictionary of thread worker info, index is ThreadId /// 线程工作者字典 索引是线程ID /// </summary> Dictionary<int, WorkerInfo> workerInfoDict = new Dictionary<int, WorkerInfo>(); /// <summary> /// The minimum timespan between thread wait sleep join updates /// 线程 等待 睡眠 加入 更新 的一个最小时间段 /// </summary> TimeSpan ThreadWaitSleepJoinCountUpdateInterval = , , , , ); /// <summary> /// A quick lookup of the number of current threads which are idle and require jobs /// 正在等待任务的线程数量 /// </summary> ; /// <summary> /// Priority queue used to order call backs /// 用于处理回调委托的优先级队列 /// </summary> PriorityQueue<WaitCallBackWrapper> jobQueue = new PriorityQueue<WaitCallBackWrapper>(); /// <summary> /// Set to true to ensure correct shutdown of worker threads. /// 是否关闭 /// </summary> bool shutdown = false; /// <summary> /// The timespan after which an idle thread will close /// 线程空闲多长时间将会关闭 /// </summary> TimeSpan ThreadIdleTimeoutClose { get; set; } /// <summary> /// The maximum number of threads to create in the pool /// 最大的线程数 /// </summary> public int MaxTotalThreadsCount { get; private set; } /// <summary> /// The maximum number of active threads in the pool. This can be less than MaxTotalThreadsCount, taking account of waiting threads. /// 线程池中活动线程的最大数量 /// </summary> public int MaxActiveThreadsCount { get; private set; } /// <summary> /// The minimum number of idle threads to maintain in the pool /// 最小线程数 /// </summary> public int MinThreadsCount { get; private set; } /// <summary> /// The most recent count of pool threads which are waiting for IO /// 正在等待的线程数 /// </summary> public int CurrentNumWaitSleepJoinThreadsCache { get; private set; } /// <summary> /// The dateTime associated with the most recent count of pool threads which are waiting for IO /// /// </summary> public DateTime LastThreadWaitSleepJoinCountCacheUpdate { get; private set; } /// <summary> /// The total number of threads currently in the thread pool /// 当前的线程数 /// </summary> public int CurrentNumTotalThreads { get { lock (SyncRoot) return threadDict.Count; } } /// <summary> /// The total number of idle threads currently in the thread pool /// 当前空闲的线程数 /// </summary> public int CurrentNumIdleThreads { get { lock (SyncRoot) return requireJobThreadsCount; } } /// <summary> /// The total number of items currently waiting to be collected by a thread /// 队列数量 /// </summary> public int QueueCount { get { return jobQueue.Count; } } /// <summary> /// Create a new NetworkComms.Net thread pool /// 创建一个新的自定义线程池 /// </summary> /// <param name="minThreadsCount">最小线程数 Minimum number of idle threads to maintain in the pool</param> /// <param name="maxActiveThreadsCount">最大活动线程数 The maximum number of active (i.e. not waiting for IO) threads</param> /// <param name="maxTotalThreadsCount">最大线程数 Maximum number of threads to create in the pool</param> /// <param name="threadIdleTimeoutClose">空闲多长时间线程被关闭 Timespan after which an idle thread will close</param> public CommsThreadPool(int minThreadsCount, int maxActiveThreadsCount, int maxTotalThreadsCount, TimeSpan threadIdleTimeoutClose) { MinThreadsCount = minThreadsCount; MaxTotalThreadsCount = maxTotalThreadsCount; MaxActiveThreadsCount = maxActiveThreadsCount; ThreadIdleTimeoutClose = threadIdleTimeoutClose; } /// <summary> /// Prevent any additional threads from starting. Returns immediately. /// 关闭 系统不会再创建新的线程 /// </summary> public void BeginShutdown() { lock (SyncRoot) shutdown = true; } /// <summary> /// Prevent any additional threads from starting and return once all existing workers have completed. /// 不再创建新的线程 当前工作都完成后就返回 /// </summary> /// <param name="threadShutdownTimeoutMS"></param> ) { List<Thread> allWorkerThreads = new List<Thread>(); lock (SyncRoot) { foreach (var thread in threadDict) { workerInfoDict[thread.Key].ThreadSignal.Set(); allWorkerThreads.Add(thread.Value); } } //Wait for all threads to finish 等待所有线程完成 foreach (Thread thread in allWorkerThreads) { try { if (!thread.Join(threadShutdownTimeoutMS)) thread.Abort(); } catch (Exception ex) { LogTools.LogException(ex, "ManagedThreadPoolShutdownError"); } } lock (SyncRoot) { jobQueue.Clear(); shutdown = false; } } /// <summary> /// Enqueue a callback to the thread pool. /// 给线程池添加要处理的任务 /// </summary> /// <param name="priority">优先级 The priority with which to enqueue the provided callback</param> /// <param name="callback">回调方法(用于处理进入的数据) The callback to execute</param> /// <param name="state">通信框架解析好的数据 The state parameter to pass to the callback when executed</param> /// <returns>Returns the managed threadId running the callback if one was available, otherwise -1</returns> public int EnqueueItem(QueueItemPriority priority, WaitCallback callback, object state) { ; lock (SyncRoot) { UpdateThreadWaitSleepJoinCountCache(); , threadDict.Count - CurrentNumWaitSleepJoinThreadsCache - requireJobThreadsCount); //int numActiveThreads = Math.Max(0,threadDict.Count - CurrentNumWaitSleepJoinThreadsCache); && numInJobActiveThreadsCount < MaxActiveThreadsCount && threadDict.Count < MaxTotalThreadsCount) { //Launch a new thread 启动一个新线程 Thread newThread = new Thread(ThreadWorker); newThread.Name = "ManagedThreadPool_" + newThread.ManagedThreadId.ToString(); newThread.IsBackground = true; WorkerInfo info = new WorkerInfo(newThread.ManagedThreadId, new WaitCallBackWrapper(callback, state)); chosenThreadId = newThread.ManagedThreadId; threadDict.Add(newThread.ManagedThreadId, newThread); workerInfoDict.Add(newThread.ManagedThreadId, info); newThread.Start(info); } && numInJobActiveThreadsCount < MaxActiveThreadsCount) { jobQueue.TryAdd(new KeyValuePair<QueueItemPriority, WaitCallBackWrapper>(priority, new WaitCallBackWrapper(callback, state))); ; foreach (var info in workerInfoDict) { //Trigger the first idle thread 触发第一个空闲线程 checkCount++; if (info.Value.ThreadIdle) { info.Value.ClearThreadIdle(); requireJobThreadsCount--; info.Value.ThreadSignal.Set(); chosenThreadId = info.Value.ThreadId; break; } if (checkCount == workerInfoDict.Count) throw new Exception("IdleThreads count is " + requireJobThreadsCount.ToString() + " but unable to locate thread marked as idle."); } } else if (!shutdown) { //If there are no idle threads and we can't start any new ones we just have to enqueue the item //如果没有空闲线程 我们不能启动新线程 只是把任务添加到队列中 jobQueue.TryAdd(new KeyValuePair<QueueItemPriority, WaitCallBackWrapper>(priority, new WaitCallBackWrapper(callback, state))); } } return chosenThreadId; } /// <summary> /// The worker object for the thread pool /// 线程池的工作者方法 /// </summary> /// <param name="state"></param> private void ThreadWorker(object state) { WorkerInfo threadInfo = (WorkerInfo)state; do { //While there are jobs in the queue process the jobs //处理队列中的任务 while (true) { if (threadInfo.CurrentCallBackWrapper == null) { KeyValuePair<QueueItemPriority, WaitCallBackWrapper> packetQueueItem; lock (SyncRoot) { UpdateThreadWaitSleepJoinCountCache(); , threadDict.Count - CurrentNumWaitSleepJoinThreadsCache - requireJobThreadsCount); if (shutdown || threadDict.Count > MaxTotalThreadsCount) //If we have too many active threads { //If shutdown was true then we may need to set thread to idle //如果 shutdown设置为True 我们需要设置线程为空闲 ) requireJobThreadsCount--; threadInfo.ClearThreadIdle(); threadDict.Remove(threadInfo.ThreadId); workerInfoDict.Remove(threadInfo.ThreadId); UpdateThreadWaitSleepJoinCountCache(); return; } else if (numInJobActiveThreadsCount > MaxActiveThreadsCount) //If we have too many active threads 活动的线程太多 { //We wont close here to prevent thread creation/destruction thrashing. //We will instead act as if there is no work and wait to potentially be timed out if (!threadInfo.ThreadIdle) { threadInfo.SetThreadIdle(); requireJobThreadsCount++; } break; } else { //Try to get a job 获取一个新任务 if (!jobQueue.TryTake(out packetQueueItem)) //We fail to get a new job 没有获取到新任务 { //If we failed to get a job we switch to idle and wait to be triggered //如果没有获取到任务 转为空闲状态并等待被触发 if (!threadInfo.ThreadIdle) { threadInfo.SetThreadIdle(); requireJobThreadsCount++; } break; } else { ) requireJobThreadsCount--; threadInfo.UpdateCurrentCallBackWrapper(packetQueueItem.Value); threadInfo.ClearThreadIdle(); } } } } //Perform the waitcallBack //执行回调方法 try { threadInfo.SetInsideCallBack(); threadInfo.CurrentCallBackWrapper.WaitCallBack(threadInfo.CurrentCallBackWrapper.State); } catch (Exception ex) { LogTools.LogException(ex, "ManagedThreadPoolCallBackError", "An unhandled exception was caught while processing a callback. Make sure to catch errors in callbacks to prevent this error file being produced."); } finally { threadInfo.ClearInsideCallBack(); } threadInfo.UpdateLastActiveTime(); threadInfo.ClearCallBackWrapper(); } //As soon as the queue is empty we wait until perhaps close time //当队列为空时 就是当前没有可以处理的任务 线程进行等待 直到超过某个时间 #if NET2 , false)) #else )) #endif { //While we are waiting we check to see if we need to close //线程如果等待了太长时间 又没有新任务来 关闭线程 if (DateTime.Now - threadInfo.LastActiveTime > ThreadIdleTimeoutClose) { lock (SyncRoot) { //We have timed out but we don't go below the minimum //如果当前线程池中的线程数太少,接近最小线程数,则不再关闭线程 if (threadDict.Count > MinThreadsCount) { ) requireJobThreadsCount--; threadInfo.ClearThreadIdle(); threadDict.Remove(threadInfo.ThreadId); workerInfoDict.Remove(threadInfo.ThreadId); UpdateThreadWaitSleepJoinCountCache(); return; } } } } //We only leave via one of our possible breaks } while (true); } /// <summary> /// Returns the total number of threads in the pool which are waiting for IO /// 返回在等待IO库总的线程数 /// </summary> private void UpdateThreadWaitSleepJoinCountCache() { lock (SyncRoot) { if (DateTime.Now - LastThreadWaitSleepJoinCountCacheUpdate > ThreadWaitSleepJoinCountUpdateInterval) { ; foreach (var thread in threadDict) { if (workerInfoDict[thread.Key].InsideCallBack && thread.Value.ThreadState == ThreadState.WaitSleepJoin) returnValue++; } CurrentNumWaitSleepJoinThreadsCache = returnValue; LastThreadWaitSleepJoinCountCacheUpdate = DateTime.Now; } } } /// <summary> /// Provides a brief string summarisation the state of the thread pool /// 提供了一个简短的字符串解释线程池中的线程的状态 /// </summary> /// <returns></returns> public override string ToString() { lock (SyncRoot) { UpdateThreadWaitSleepJoinCountCache(); return "TotalTs:" + CurrentNumTotalThreads.ToString() + ", IdleTs:" + CurrentNumIdleThreads.ToString() + ", SleepTs:" + CurrentNumWaitSleepJoinThreadsCache.ToString() + ", Q:" + QueueCount.ToString(); } } } /// <summary> /// A private wrapper used by CommsThreadPool /// 工作者信息类 提供给CommsThreadPool线程池使用 /// </summary> class WorkerInfo { public int ThreadId { get; private set; } public AutoResetEvent ThreadSignal { get; private set; } public bool ThreadIdle { get; private set; } public DateTime LastActiveTime { get; private set; } public WaitCallBackWrapper CurrentCallBackWrapper { get; private set; } public bool InsideCallBack { get; private set; } public WorkerInfo(int threadId, WaitCallBackWrapper initialisationCallBackWrapper) { ThreadSignal = new AutoResetEvent(false); ThreadIdle = false; ThreadId = threadId; LastActiveTime = DateTime.Now; this.CurrentCallBackWrapper = initialisationCallBackWrapper; } public void UpdateCurrentCallBackWrapper(WaitCallBackWrapper waitCallBackWrapper) { CurrentCallBackWrapper = waitCallBackWrapper; } public void UpdateLastActiveTime() { LastActiveTime = DateTime.Now; } public void ClearCallBackWrapper() { CurrentCallBackWrapper = null; } /// <summary> /// Set InsideCallBack to true /// 设置内部回调为True /// </summary> public void SetInsideCallBack() { InsideCallBack = true; } /// <summary> /// Set InsideCallBack to false /// 设置内部回调为False /// </summary> public void ClearInsideCallBack() { InsideCallBack = false; } /// <summary> /// Set threadIdle to true /// 设置线程空闲为True /// </summary> public void SetThreadIdle() { this.ThreadIdle = true; } /// <summary> /// Set threadIdle to false /// 设置线程空闲为False /// </summary> public void ClearThreadIdle() { this.ThreadIdle = false; } } #endif /// <summary> /// A private wrapper used by CommsThreadPool /// 一个回调的包装器 在自定义线程池中使用 /// </summary> class WaitCallBackWrapper { public WaitCallback WaitCallBack { get; private set; } public object State { get; private set; } public WaitCallBackWrapper(WaitCallback waitCallBack, object state) { this.WaitCallBack = waitCallBack; this.State = state; } }
介绍开源的.net通信框架NetworkComms框架 源码分析(十五 ) CommsThreadPool自定义线程池的更多相关文章
- DotNetty网络通信框架学习之源码分析
DotNetty网络通信框架学习之源码分析 有关DotNetty框架,网上的详细资料不是很多,有不多的几个博友做了简单的介绍,也没有做深入的探究,我也根据源码中提供的demo做一下记录,方便后期查阅. ...
- 深入理解分布式调度框架TBSchedule及源码分析
简介 由于最近工作比较忙,前前后后花了两个月的时间把TBSchedule的源码翻了个底朝天.关于TBSchedule的使用,网上也有很多参考资料,这里不做过多的阐述.本文着重介绍TBSchedule的 ...
- 设计模式(十五)——命令模式(Spring框架的JdbcTemplate源码分析)
1 智能生活项目需求 看一个具体的需求 1) 我们买了一套智能家电,有照明灯.风扇.冰箱.洗衣机,我们只要在手机上安装 app 就可以控制对这些家电工作. 2) 这些智能家电来自不同的厂家,我们不想针 ...
- 设计模式(二十一)——解释器模式(Spring 框架中SpelExpressionParser源码分析)
1 四则运算问题 通过解释器模式来实现四则运算,如计算 a+b-c 的值,具体要求 1) 先输入表达式的形式,比如 a+b+c-d+e, 要求表达式的字母不能重复 2) 在分别输入 a ,b, c, ...
- $Django cbv源码分析 djangorestframework框架之APIView源码分析
1 CBV的源码分析 #视图 class login (View): pass #路由 url(r'^books/$', views.login.as_view()) #阅读源码: #左侧工程栏--- ...
- Android源码分析(五)-----如何从架构师的角度去设计Framework框架
一 : 架构与程序 软件架构是一种思维方式,而程序只是实现思维方式的一种手段,代码固然重要,但是若没有整体的思维架构,一切程序都如水中浮萍. 二 : 框架如何设计 暂时抛开Android Framew ...
- NIO框架之MINA源码解析(五):NIO超级陷阱和使用同步IO与MINA通信
1.NIO超级陷阱 之所以说NIO超级陷阱,就是因为我在本系列开头的那句话,因为使用缺陷导致客户业务系统瘫痪.当然,我对这个问题进行了很深的追踪,包括对MINA源码的深入了解,但其实之所以会出现这个问 ...
- ④NuPlayer播放框架之Renderer源码分析
[时间:2016-11] [状态:Open] [关键词:android,nuplayer,开源播放器,播放框架,渲染器,render] 0 导读 之前我们分析了NuPlayer的实现代码,本文将重点聚 ...
- ⑤NuPlayer播放框架之GenericSource源码分析
[时间:2017-01] [状态:Open] [关键词:android,nuplayer,开源播放器,播放框架,GenericSource] 0 导读 GenericSource是NuPlayer:: ...
随机推荐
- java 泛型思考
java泛型并没有像C++那样原生支持,因此,为了保证迁移兼容性,编译器在编译时会擦除具体类型,因此不能通过泛型调用具体方法. 如果调用必须用extends关键字限定范围,也正是由于这个原因,java ...
- C#中动态读写App.config配置文件
转自:http://blog.csdn.net/taoyinzhou/article/details/1906996 app.config 修改后,如果使用cofnigurationManager立即 ...
- linux服务之maven
curl -O http://mirrors.noc.im/apache/maven/maven-3/3.3.9/binaries/apache-maven-3.3.9-bin.zip [root@d ...
- STM32F4 SPI2初始化及收发数据【使用库函数】
我的STM32F4 Discovery上边有一个加速度传感器LIS302DL.在演示工程中,ST的工程师使用这个传感器做了个很令人羡慕的东西:解算开发板的姿态.当开发板倾斜时候,处于最上边的LED点亮 ...
- 封装实现一个自己的tabbar
实现效果:
- RMAN_学习笔记2_RMAN Setup配置和监控
2014-12-23 Created By BaoXinjian
- python(23)re函数:compile、match、search、findall
正则表达式是一个特殊的字符序列,它能帮助你方便的检查一个字符串是否与某种模式匹配. Python 自1.5版本起增加了re 模块,它提供 Perl 风格的正则表达式模式. re 模块使 Python ...
- FreeBSD 10 中文环境
中文字体位置 FontPath "/usr/local/lib/X11/fonts/misc/:unscaled" FontPath "/us ...
- 高亮代码显示之HTML困惑
近期做样式库,需要将HTML代码高亮,开始寻找相关的插件. 看到highlight.js,看到它主题样式如此之多,支持语言也如此之多,以为找到了神器.不想这只是痛苦的开始,为了让它支持HTML,我尝试 ...
- windows下PHP5.5.6+Apache2.4.7配置
本文主要阐述在windows8及win8.1 环境下搭建PHP5.5.6+Apache2.4.7. 1.软件准备 apache 2.4.7:http://pan.baidu.com/s/1iUPif ...