Net线程池设计
Net线程池设计
功能描述:
- 支持创建多个线程池,并统一管理
- 支持不同线程池的容量控制,以及最少活动线程的设置
- 支持不同线程池中活动线程的闲时设置,即线程空闲时间到期后即自动被回收
结构设计:
- ThreadWorkerPoolManager: 线程池管理器,用于统一创建,获取,销毁线程池,使用单例模式
- ThreadWorkerPool: 线程池,用于管理指定数量的线程,由ThreadWorkerPoolManager管理,自身无法创建与销毁
- TheadWorkerPoolItem: 线程池项,用于包装线程工作器,协助ThreadWorkerPool更好的管理线程,例如取出,放回,闲时的控制
- TheadWorker: 线程工作器,用于包装系统线程System.Threading.Thread,使其可以重复使用,减少Thrad创建和销毁的性能开销
结构关系图:

详细设计:
ThreadWoker
要点设计:
- 完成一次任务后,System.Threading.Thread不能被系统销毁, 默认情况下new Thread(ThreadStart start).Start(), 当ThreadStart委托的任务完成后,系统将销毁该线程,也就是说创建一个System.Threading.Thread实例只能使用一次;为了使线程能被重复使用,ThreadWoker将使用 while+sleeping 的方式对系统线程进行包装,同时使用AutoResetEvent代替Thread.Sleep(timeout)来达到更佳的控制
- 闲时设计,线程资源是极其宝贵的系统资源,如果线程池中存在大量的空闲线程这是一种浪费,极端情况下将影响系统的稳定性和工作效率;ThreadWorker将使用AutoResetEvent和事件通知的方式来代替在线程池中定期轮询检查的方式,每完成一个任务将重新开始空闲时间的计算,如果ThreadWorker在线程池中被取出,那么ThreadWorker空闲时间将永远不会到期,直到ThreadWorker被返回线程池后才重新开始空闲时间的计算
状态图:

关键代码:

1 private void ThreadWorking()
2 {
3 while (_status != ThreadWorkerStatus.Abort)
4 {
5 //WaitOne 返回false表示等待超时,true接到取消等待的通知
6 //这里利用AutoResetEvent.WaitOne的特性来设计闲时控制,false表示空闲到期,true表示新的任务开始
7 if (!_waitEvent.WaitOne(_idleTime))
8 {
9 if (!_isCanIdleExpired) //_isCanIdleExpired变量控制是否允许超时,例如被取出后将不能超时
10 continue;
11
12 _status = ThreadWorkerStatus.Abort;
13 _waitEvent.Close();
14 _waitEvent.Dispose();
15 if (OnIdleExpired != null)
16 OnIdleExpired(this, null); //空闲到期事件通知
17 return;
18 }
19 else if (_status == ThreadWorkerStatus.Abort)
20 return;
21
22 try
23 {
24 Working();
25 }
26 catch (Exception ex)
27 {
28 _logger.TraceEvent(TraceEventType.Error, (int)TraceEventType.Error, ex.ToString());
29 }
30 finally
31 {
32 _status = ThreadWorkerStatus.Idle;
33 if (OnWorkCompleted != null)
34 OnWorkCompleted(this, null); //任务完成事件通知
35 }
36 }
37 }


1 public void Work()
2 {
3 if (_status == ThreadWorkerStatus.Abort)
4 throw new InvalidOperationException("this ThreadWorker was Abort!");
5
6 if (_status == ThreadWorkerStatus.Working)
7 throw new InvalidOperationException("this ThreadWorker was working, unable to duplicate work!");
8
9 _status = ThreadWorkerStatus.Working;
10 _waitEvent.Set(); //通知线程有个新的工作要开始
11 }

ThreadWorkerPoolItem
要点设计:
- 链接ThreadWorker和线程池,线程池通过ThreadWorkerPoolItem控制ThreadWorker在线程池的取出,放回,销毁
- 通过订阅ThreadWorker的空闲到期事件OnIdleExpired,来完成线程池对线程的移除
- 通过订阅ThreadWorker的任务完成事件OnWorkCompleted,来完成线程返回线程池的操作
- 提供剩余空闲时间查询,来为线程池提供更优线程取出方案
完整代码:

1 public sealed class ThreadWorkerPoolItem
2 {
3 private ThreadWorkerPoolItemStatus _status;
4 private readonly ThreadWorkerBase _threadWorker;
5 private readonly ThreadWorkerPoolBase _threadWorkerPool;
6 private readonly int _idleTime;
7 private DateTime _startIdleTime;
8
9 internal ThreadWorkerPoolItem(ThreadWorkerPoolBase pool, ThreadWorkerBase threadWorker, ThreadWorkerPoolSettings poolSettings)
10 {
11 _threadWorkerPool = pool;
12 _threadWorker = threadWorker;
13 _threadWorker.OnIdleExpired += _threadWorker_OnIdleExpired;
14 _threadWorker.OnWorkCompleted += _threadWorker_OnWorkCompleted;
15 _threadWorker.Start();
16 _status = ThreadWorkerPoolItemStatus.Idle;
17 _idleTime = poolSettings.IdleTime;
18 }
19
20 void _threadWorker_OnWorkCompleted(object sender, EventArgs args)
21 {
22 _threadWorkerPool.Return(this);
23 }
24
25 void _threadWorker_OnIdleExpired(object sender, EventArgs args)
26 {
27 _threadWorkerPool.Remove(this);
28 }
29
30 internal ThreadWorkerPoolItemStatus Status
31 {
32 get
33 {
34 if (_threadWorker.Status == ThreadWorkerStatus.Abort || _status == ThreadWorkerPoolItemStatus.Abort)
35 return ThreadWorkerPoolItemStatus.Abort;
36
37 return _status;
38 }
39 }
40
41 internal int SurplusIdleTime
42 {
43 get
44 {
45 if (_status == ThreadWorkerPoolItemStatus.Take || _idleTime == -1)
46 return -1;
47
48 int idledTime = (int)(_startIdleTime - DateTime.Now).TotalMilliseconds;
49 if (idledTime >= _idleTime)
50 return 0;
51
52 return idledTime;
53 }
54 }
55
56 internal void SetTake()
57 {
58 _threadWorker.IsCanIdleExpried = false;
59 _status = ThreadWorkerPoolItemStatus.Take;
60 }
61
62 internal void SetIdle()
63 {
64 _startIdleTime = DateTime.Now;
65 _status = ThreadWorkerPoolItemStatus.Idle;
66 _threadWorker.IsCanIdleExpried = true;
67 }
68
69 internal ThreadWorkerBase ThreadWorker
70 {
71 get { return _threadWorker; }
72 }
73 }

ThreadWorkerPool
要点设计:
- 使用Lock配合ThreadWorkerPoolItem的状态来确保多线程下,每次取出的都是空闲的ThreadWorker
- 取出的超时设计,由于线程池有容量控制,高并发下必然导致线程池满负荷,提供超时设置,有利于使用者自行控制满负荷情况下的处理;ThreadWorkerPool将使用while+sleeping的方式,同时使用AutoResetEvent代替Thread.Sleep(timeout)来达到更佳的控制,当一个线程被放回线程池时,另一等待获取者立即获取,而无需等待下一次轮询的到来
关键代码:

1 protected bool TryTake(int timeout, out ThreadWorkerBase threadWorker)
2 {
3 threadWorker = null;
4 lock (_takeLocker)
5 {
6 ThreadWorkerPoolItem worker = null;
7 DateTime startWaitTime;
8 while (!_isDestoryed)
9 {
10 worker = _threadWorkerList.Where(e => e.Status == Core.ThreadWorkerPoolItemStatus.Idle).OrderByDescending(e => e.SurplusIdleTime).FirstOrDefault();
11 if (worker == null)
12 {
13 if (_threadWorkerList.Count < _settings.MaxThreadWorkerCount)
14 {
15 worker = this.CreatePoolItem(_threadWorkerList.Count + 1, _settings.IdleTime);
16 worker.SetTake();
17 _threadWorkerList.Add(worker);
18 threadWorker = worker.ThreadWorker;
19 return true;
20 }
21
22 startWaitTime = DateTime.Now;
23 if (!_takeWaitEvent.WaitOne(timeout))
24 {
25 threadWorker = null;
26 return false;
27 }
28
29 if (timeout != -1)
30 {
31 timeout = timeout - (int)(DateTime.Now - startWaitTime).TotalMilliseconds;
32 if (timeout <= 0)
33 {
34 threadWorker = null;
35 return false;
36 }
37 }
38 continue;
39 }
40
41 threadWorker = worker.ThreadWorker;
42 worker.SetTake();
43 return true;
44 }
45
46 threadWorker = null;
47 return false;
48 }
49 }

1 internal void Return(ThreadWorkerPoolItem item)
2 {
3 item.SetIdle();
4 _takeWaitEvent.Set();
5 }
ThreadWorkerPoolManager使用单例模式管理,代码过于简单这里就不贴了......
有兴趣的同学可以点击这里进行下载源码查看:Nutshell.ThreadWorkerPool.zip
github 开源地址: https://github.com/zcylife/Nutshell
Net线程池设计的更多相关文章
- 【转载】深度解读 java 线程池设计思想及源码实现
总览 开篇来一些废话.下图是 java 线程池几个相关类的继承结构: 先简单说说这个继承结构,Executor 位于最顶层,也是最简单的,就一个 execute(Runnable runnable) ...
- Java并发指南12:深度解读 java 线程池设计思想及源码实现
深度解读 java 线程池设计思想及源码实现 转自 https://javadoop.com/2017/09/05/java-thread-pool/hmsr=toutiao.io&utm_ ...
- Nutshell.ThreadWorkerPool .Net线程池设计
功能描述: 支持创建多个线程池,并统一管理 支持不同线程池的容量控制,以及最少活动线程的设置 支持不同线程池中活动线程的闲时设置,即线程空闲时间到期后即自动被回收 结构设计: ThreadWorker ...
- Java - 线程池设计与选择
http://ifeve.com/how-to-calculate-threadpool-size/ 任务一般可分为:CPU密集型.IO密集型.混合型,对于不同类型的任务需要分配不同大小的线程池. C ...
- 谈谈Java的线程池设计
在实际项目中,如果因为想异步执行暂时性的任务而不断创建线程是很浪费资源的事情(当一个任务执行完后,线程也没用了).这种情况下,最好是将任务提交给线程池执行. 所谓池,就是将管理某一种资源,对资源进行复 ...
- 分享一个自制的 .net线程池
扯淡 由于项目需求,需要开发一些程序去爬取一些网站的信息,算是小爬虫程序吧.爬网页这东西是要经过网络传输,如果程序运行起来串行执行请求爬取,会很慢,我想没人会这样做.为了提高爬取效率,必须使用多线程并 ...
- 线程池原理及创建(C++实现)
http://www.cnblogs.com/lidabo/p/3328402.html 本文给出了一个通用的线程池框架,该框架将与线程执行相关的任务进行了高层次的抽象,使之与具体的执行任务无关.另外 ...
- 线程池原理及创建并C++实现
本文给出了一个通用的线程池框架,该框架将与线程执行相关的任务进行了高层次的抽象,使之与具体的执行任务无关.另外该线程池具有动态伸缩性,它能根据执行任务的轻重自动调整线程池中线程的数量.文章的最后,我们 ...
- C#的线程池的那些事
最近在做站时发现,线程池的问题很棘手,所以总结了一篇关于线程池的文章,原文地址:http://www.shuonar.com/blog/ac16496b-87ec-4790-a9ea-d69bbffa ...
随机推荐
- crontab,at命令,常见问题
crontab命令 前 一天学习了 at 命令是针对仅运行一次的任务,循环运行的例行性计划任务,linux系统则是由 cron (crond) 这个系统服务来控制的. Linux 系统上面原本就有非常 ...
- JQuery 插件 - 弹窗:BlockUI
JQuery的弹窗插件,网上实在有很多做的比较好的,比如artDialog.layer,甚至EasyUI等等.这些在效果上做的非常好.但我觉得一个小小的弹窗提示,没有必要引用这些(其实是有点大材小用了 ...
- HDU_1238——最大子串搜索
Problem Description You are given a number of case-sensitive strings of alphabetic characters, find ...
- word-wrap: break-word 和 word-break: break-all 到底有啥区别?
做项目改bug的时候,遇到过好多次,要么是文本超出文本区域,或者单词太长(一般是url链接中的一些鬼),把装它的标签强制撑大,导致一些响应式问题.除此之外,还有很多问题,每次都是恍然醒悟,然后又在网上 ...
- 关于AppStore上传相关问题
1.电脑本地证书CertificateSigningRequest.certSigningRequest一定要一致(包括开发者证书,尤其是发布证书要一致,否则无法正常上传),此类错误Xcode一般会提 ...
- [Polymer] Introduction
install Polymer and explore creating our first custom element: bower install polymer index.html: < ...
- 基于MFC的socket编程(异步非阻塞通信)
对于许多初学者来说,网络通信程序的开发,普遍的一个现象就是觉得难以入手.许多概念,诸如:同步(Sync)/异步(Async),阻塞(Block)/非阻塞(Unblock)等,初学者往往迷惑不清, ...
- Qt - 与众不同的电子时钟
Qt的电子时钟是个老掉牙的demo了,但是利用lcdNumber显示的样子非常老土(下图第一个显示效果),一看就知道是从qt帮助文档里摘出来的example,毫无新意. 美化一下系统时钟,抛开固有控 ...
- 内部类之.this&&.new
一..this 我们都知道this是指当前类中的对象本身,但是在内部类中需要指明外部类时,this不再起作用,那应该怎么做呢?下面,让我们看看: public class DotThis { void ...
- ICE 介绍及实现
.ICE是什么? ICE是ZEROC的开源通信协议产品,它的全称是:The Internet Communications Engine,翻译为中文是互联网通信引擎,是一个面向对象的中间件,使我们能够 ...