介绍开源的.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:: ...
随机推荐
- 怎么 才能显示Eclipse中Console的全部内容
可以如下设置 preference->run/debug->console 设置limit console output 为false,方便调试时,查看全部console. 这个真是太有用 ...
- google protocol buffer 使用说明
一:编译源码 下载地址:http://code.google.com/p/protobuf/downloads/list 下载后,根据编译说明进行编译. windows 平台,直接打开msvc中的工程 ...
- 【巩固】CSS3的animation基础
终于结束了最后css3的一节课,关于animation的使用,其实之前已经用过一次.大致要了解的就是,关于如何让动画停在最后一帧的方法.视频里有提到过css3出了个新的样式可以实现,但是老师没有记住, ...
- Android学习笔记(八)
android中常见空间的使用方法 1.TextView TextView主要用于在界面上显示一段文本信息,如下面代码所示: <LinearLayout xmlns:android=" ...
- 本地和VMware虚拟主机之间的网络访问
在需要设置的虚拟主机节点上右键,点击[设置...] 在打开的虚拟机设置中,选中[网络适配器],之后在右边设置网络连接为[自定义:指定的虚拟网络] 然后设置同一网关即可.
- [MySQL] SQL_ERROR 1032解决办法
一.缘由: 在主主同步的测试环境,由于业务侧没有遵循同一时间只写一个点的原则,造成A库上删除了一条数据,B库上在同时更新这条数据. 由于异步和网络延时,B的更新event先到达A端执行,造成A端找不到 ...
- phonegap(cordova)环境配置
首先要配置好 java jdk 和 java jre 环境 配置之后 控制台 javac -version 查看是否配置成功 然后配置 Android sdk 配置之后 控制台 输入 adb 查看 ...
- 甲状腺癌怎样早发现 可B超检查
2013-12-13 14:40:00.0 本文来源:人民网 点击参与跟帖 原标题:健康之道:甲状腺癌怎样早发现 摘要:甲状腺癌怎样早发现呢?隐早期以甲状腺结节的方式存在,且以匿方式生长,可能在人们偶 ...
- 玩转单元测试之Testing Spring MVC Controllers
玩转单元测试之 Testing Spring MVC Controllers 转载注明出处:http://www.cnblogs.com/wade-xu/p/4311657.html The Spri ...
- 【解决】SharePoint外部列表保存的日期/时间值不正确
[问题描述]: 在SharePoint中创建一个外部列表后,通过工作流或直接通过外部列表中的新增向外部列表添加数据项.通过外部列表或数据库查看添加的数据项时发现日期类型字段的值都不正确,像是差了若干个 ...