使用VC实现一个“智能”自增减线程池
工作中接手了一款产品的改造。因为该产品可能使用很多线程,所以产品中使用了线程池。(转载请指明来自BreakSoftware的CSDN博客)
线程池的一个优点是降低线程创建和销毁的频率;缺点是可能在比较闲的时候还存在一定数量的空闲线程。这个也可以比作现实生活中的武器,对于一款武器,有其攻击的能力和防御的能力。有些设计可能会将攻击力做的很强但是防御力有所折扣,有些可能防御做的很好但是攻击力不足。于是如果将这些设计放在一起可能就很难比较个好坏来,但是可能很容易比较出一个“哪个更适合哪种战场”。
于是,回到我们的产品。这款产品原始的线程池一开始时便创建了上百个休眠线程,可以说火力十足啊。但是我们评估后,我们认为大部分场景这些线程可能一辈子都在睡眠!这样的设计在我们预估的场景中明显是“不适宜”的。于是我接到一个任务就是改造之。让其成为一个根据需求可以自增减的线程池。
对于自增减,这便是种策略,又回到攻击力和防御力的博弈上来。还是那句话:适合的才是好的。可以想象,如果自增减的频率过快,那干嘛使用线程池呢?如果过慢,那么干嘛自增减呢?我们的场景:线程池中的任务的增速不会快,减数可能快。目前我写的demo版中,我初始时建立了10个线程,当空闲线程等于1个时,我就会尝试再新建10个线程,当增加到30个线程时,就不增加线程了,任务会保留在列表中,待有空闲线程时去执行。当空闲线程数大于等于当前线程数一半时,我就会查看如果释放了10个线程,空闲线程是否小于等于我设置的最低空闲线程数,如果是,则不释放,否则就释放。当然这只是大致的逻辑。
m_ThreadPool.Create( 30, 10, 10, 1 ); //最大线程数 最低线程数 递变数 最低空闲线程数
在demo中,我使用MFC写了个例子(Console版懒得写了)。其中DICThreadPool.h和DICThreadPool.cpp是线程池的相关实现,DICTaskObject.h中是任务要继承的基类。WorkerThread.h和WorkerThread.cpp是任务的实现,这个代码根据不同的业务改变而改变(你可定制),它中包含的类CWorkerThread要继承DICTaskObject.h中的CDICTaskObject,并实现基类中的几个虚函数。
DICTaskObject.h
enum EThreadRoutineExitType
{WAITEVENTOK = 0,OTHERRESON = 1
};class CDICTaskObject
{
public:CDICTaskObject(){};virtual ~CDICTaskObject(){};
public:virtual EThreadRoutineExitType Run() = 0;virtual BOOL AutoDelete() = 0;HANDLE m_hStopEvent;
};
WorkerThread.h
class CWorkerThread: public CDICTaskObject
{
public:CWorkerThread();~CWorkerThread();public:VOID SetAutoDelete( BOOL bAutoDel );// 以下增加你的成员函数protected:EThreadRoutineExitType Run();BOOL AutoDelete();private:// 以下增加你的成员函数private:BOOL m_bAutoDelete;// 以下增加你的成员变量};
这个类的实例一半都是new出来的,但是往往因为时机的问题,只有在相关操作执行后才可以delete掉它。于是线程池便提供了一个功能就是负责delete掉这个实例,要想让线程池去delete,就要调用SetAutoDelete(TRUE)。
CWorkerThread* pWorkerThread = new CWorkerThread;pWorkerThread->SetAutoDelete( TRUE );
线程池创建后,要让线程池去执行这个任务,就可以
m_ThreadPool.Run( pWorkerThread );
剩下的事就交给线程池去做吧。
再说一下线程池模型。
可以看见线程池做的事情还是很简单的。它只是负责保存任务、唤醒线程和新建一批新线程。
线程的职责就是取任务执行任务,并判断是否需要减少线程数(带有一定的管理职责,让管理行为由一些行为触发可能比定时去检测要智能些)。
MFC那个例子
先创建线程池,然后新建任务,我会在屏幕中弹出一些窗口,这些窗口的存在周期由右侧的执行时间来决定。
如果想查看详细信息,可以在debugview中设置过滤:
然后我们可以查看刚才的日志
DeInCreaseThreadPool:Create thread 12508 and suspend it
DeInCreaseThreadPool:Create thread 10548 and suspend it
DeInCreaseThreadPool:Create thread 10648 and suspend it
DeInCreaseThreadPool:Create thread 10812 and suspend it
DeInCreaseThreadPool:Create thread 6336 and suspend it
DeInCreaseThreadPool:Create thread 10544 and suspend it
DeInCreaseThreadPool:Create thread 11712 and suspend it
DeInCreaseThreadPool:Create thread 8904 and suspend it
DeInCreaseThreadPool:Create thread 3388 and suspend it
DeInCreaseThreadPool:Create thread 7824 and suspend it
DeInCreaseThreadPool:Resume thread 3388
DeInCreaseThreadPool:Resume thread 6336
DeInCreaseThreadPool:Resume thread 7824
DeInCreaseThreadPool:Resume thread 8904
DeInCreaseThreadPool:Resume thread 10544
DeInCreaseThreadPool:Resume thread 10548
DeInCreaseThreadPool:Resume thread 10648
DeInCreaseThreadPool:Resume thread 10812
DeInCreaseThreadPool:Resume thread 11712
DeInCreaseThreadPool:Resume thread 12508
DeInCreaseThreadPool:Create 10 Threads
是初始创建线程池(最低10个,Create中设置的)
DeInCreaseThreadPool:Inset a low priority task in the list
DeInCreaseThreadPool:ThreadPool is not Full,the task is being excuted in thread 3388
DeInCreaseThreadPool:Get a task from the list
这段是插入一个任务,然后3388号线程负责了这个任务
DeInCreaseThreadPool:Inset a low priority task in the list
DeInCreaseThreadPool:There is 1 free threads,but the min count of free threads is 1,so I will create more threads
DeInCreaseThreadPool:Create thread 3176 and suspend it
DeInCreaseThreadPool:Create thread 12192 and suspend it
DeInCreaseThreadPool:Create thread 8596 and suspend it
DeInCreaseThreadPool:Create thread 7628 and suspend it
DeInCreaseThreadPool:Create thread 10612 and suspend it
DeInCreaseThreadPool:Create thread 10060 and suspend it
DeInCreaseThreadPool:Create thread 1692 and suspend it
DeInCreaseThreadPool:Create thread 12400 and suspend it
DeInCreaseThreadPool:Create thread 7436 and suspend it
DeInCreaseThreadPool:Create thread 8272 and suspend it
DeInCreaseThreadPool:Resume thread 1692
DeInCreaseThreadPool:Resume thread 3176
DeInCreaseThreadPool:Resume thread 7436
DeInCreaseThreadPool:Resume thread 7628
DeInCreaseThreadPool:Resume thread 8272
DeInCreaseThreadPool:Resume thread 8596
DeInCreaseThreadPool:Resume thread 10060
DeInCreaseThreadPool:Resume thread 10612
DeInCreaseThreadPool:Resume thread 12192
DeInCreaseThreadPool:Resume thread 12400
这段是因为刚开始的10个线程中只剩下1个空闲线程了,等于我们设置的最低空闲线程,于是就会再创建10个线程
DeInCreaseThreadPool:Inset a low priority task in the list
DeInCreaseThreadPool:There is 1 free threads,but the min count of free threads is 1,so I will create more threads
DeInCreaseThreadPool:There is 30 threads,but the max count of threads is 30,so I can't create 10 threads
DeInCreaseThreadPool:ThreadPool is not Full,the task is being excuted in thread 13728
DeInCreaseThreadPool:Get a task from the list
DeInCreaseThreadPool:Inset a low priority task in the list
DeInCreaseThreadPool:There is 0 free threads,but the min count of free threads is 1,so I will create more threads
DeInCreaseThreadPool:There is 30 threads,but the max count of threads is 30,so I can't create 10 threads
DeInCreaseThreadPool:Get a task from the list
DeInCreaseThreadPool:ThreadPool is not Full,the task is being excuted in thread 13808
DeInCreaseThreadPool:Inset a low priority task in the list
DeInCreaseThreadPool:There is 0 free threads,but the min count of free threads is 1,so I will create more threads
DeInCreaseThreadPool:There is 30 threads,but the max count of threads is 30,so I can't create 10 threads
DeInCreaseThreadPool:ThreadPool is Full,the task is waiting for a free thread to excute
这是不断有新任务被插入到任务列表中,而线程池满了的情况。
DeInCreaseThreadPool:There is 16 working threads,more than half of the count(30) of threads,I will not decrease the size of the thread pool
DeInCreaseThreadPool:Task of _ThreadProc 9028 is completed,delete the object of the task
DeInCreaseThreadPool:There is 15 working threads,more than half of the count(30) of threads,I will attempt to decrease the size of the thread pool
DeInCreaseThreadPool:I will decrease the thread pool by 10
DeInCreaseThreadPool:_ThreadProc 4612 Exit 1
DeInCreaseThreadPool:_ThreadProc 5132 Exit 1
DeInCreaseThreadPool:_ThreadProc 5240 Exit 1
DeInCreaseThreadPool:_ThreadProc 6608 Exit 1
DeInCreaseThreadPool:_ThreadProc 7628 Exit 1
DeInCreaseThreadPool:_ThreadProc 7720 Exit 1
DeInCreaseThreadPool:_ThreadProc 7724 Exit 1
DeInCreaseThreadPool:_ThreadProc 8224 Exit 1
DeInCreaseThreadPool:_ThreadProc 8272 Exit 1
DeInCreaseThreadPool:_ThreadProc 8496 Exit 1
这是一些任务完成了,空闲线程达到了当前线程一半了,就释放掉10个线程(Create中设置的递变线程数)。
DeInCreaseThreadPool:The Count of Current Threads is 20.
DeInCreaseThreadPool:The Count of Current Working Threads is 9.
DeInCreaseThreadPool:The Count of Need Free Threads is 10.
DeInCreaseThreadPool:The Count of Min Free Threads is 1.
DeInCreaseThreadPool:If I decrease thread pool size,the count of free threads is less than min free count.I will not decrease the size of thread pool
DeInCreaseThreadPool:Task of _ThreadProc 11696 is completed,delete the object of the task
DeInCreaseThreadPool:There is 8 working threads,more than half of the count(20) of threads,I will attempt to decrease the size of the thread pool
DeInCreaseThreadPool:I will decrease the thread pool by 10
DeInCreaseThreadPool:_ThreadProc 7700 Exit 1
DeInCreaseThreadPool:_ThreadProc 7708 Exit 1
DeInCreaseThreadPool:_ThreadProc 8596 Exit 1
DeInCreaseThreadPool:_ThreadProc 8616 Exit 1
DeInCreaseThreadPool:_ThreadProc 8740 Exit 1
DeInCreaseThreadPool:_ThreadProc 9028 Exit 1
DeInCreaseThreadPool:_ThreadProc 9476 Exit 1
DeInCreaseThreadPool:_ThreadProc 10004 Exit 1
DeInCreaseThreadPool:_ThreadProc 10548 Exit 1
DeInCreaseThreadPool:_ThreadProc 10648 Exit 1
这是在递减到接近最低线程数的场景。
以下是该工程地址
DeInCreaseThreadPool
(转载请指明出处)
最后附上百度云盘的下载地址:http://pan.baidu.com/s/1pJpziiB,密码:fmgq
相关文章:

国内外财务软件科目结构的比较
科目结构是整个会计核算的基础。国内外财务软件都是任意定义科目的分段及科目编码长度,一般都能支持六段到九段。但科目结构在不同的国家有不同的规范,因而在不同的财务软件中也就有不同的控制。在科目分类上,国内外有明显的区别。国外财务软…
朋友圈装死,微博蹦迪,Python教你如何掌握女神情绪变化 | CSDN博文精选
作者 | A字头来源 | 数据札记倌很多人都是在朋友圈装死,微博上蹦迪。微信朋友圈已经不是一个可以随意发表心情的地方了,微博才是!所以你不要傻傻盯着女神的朋友圈发呆啦!本文教你如何用Python自动通知女神微博情绪变化,…

java异常笔记
Throwable是所有Java程序中错误处理的父类,有两种资类:Error和Exception。Error:表示由JVM所侦测到的无法预期的错误,由于这是属于JVM层次的严重错误,导致JVM无法继续执行,因此,这是不可捕捉到的…
2019最新进展 | Transformer在深度推荐系统中的应用
作者 | Alex-zhai来源 | 深度传送门(ID:deep_deliver)【导读】最近基于Transformer的一些NLP模型很火(比如BERT,GPT-2等),因此将Transformer模型引入到推荐算法中是近期的一个潮流。Transformer比起传统的L…

自己架设windows升级服务器
大部分对计算机比较熟悉的朋友都知道,通常安装好Windows 操作系统后要做的第一件事就是上Windows Update网站去给Windows 安装补丁程序,否则各种漏洞对系统就是一个很大的威胁。不过遗憾的是很多人还没有这样的意识,疏忽了给系统打补丁。这也…

内嵌IE网页窗口中消除IE默认脚本设置影响的方法
随着人们对客户端软件界面要求的不断提高,软件开发商面临着一个问题:如何快速廉价开发出各种丰富效果的UI界面。设计出一套丰富控件的界面库是不容易的,且产品经理丰富的想法和UED对效果的追求,往往会使程序员疲于编写这些“效果控件”。目前市面上使用的很多界面库是基于X…

win7 64位操作系统中 Oracle 11g 安装教程(图解)
1.下载Oracle 11g R2 for Windows版本,下载地址如下 官方网站: http://download.oracle.com/otn/nt/oracle11g/112010/win32_11gR2_database_1of2.zip http://download.oracle.com/otn/nt/oracle11g/112010/win32_11gR2_database_2of2.zip 2.解压两…

使用APIHOOK实现进程隐藏
今天翻出一些今年前写的代码。其中一个是09年,我帮一个读研的同学写的一个“无公害恶意”程序。大致要求就是要实现自启动和自我隐藏。我使用的都是些简单的技术,只是实现自我隐藏稍微让我花费了点时间写算法。其实这个算法也很简单,就是大学…
程序员创业前要做哪些准备?
作者 | hsm_computer出品 | CSDN博客在互联网时代,不少干IT的人白手起家,在短短的几年里通过努力干出了一番事业,有房有车有公司,在人前也很光鲜。这就吸引了更多的程序员想要通过自主创业来实现财务自由。殊不知,创业…

Flex编码过程
Flex编码过程当我们开发一个Flex程序,我们重复其他类型网络程序的过程,例如HTML,JSP,ASP和CFML。创建一个有用的Flex程序是很容易的:打开我们最喜欢的文本编辑器,例如Flex Builder,输入XML标签,编译成为SWF…

BufferedWriter
package JBJADV003;import java.io.*;public class BufferedWriterTest { public static void main(String[] args) { try { //创建一个FileWriter 对象 FileWriter fwnew FileWriter("c:\\myDoc\\hello.txt"); //创建一个BufferedWriter 对象 BufferedWriter bwnew…
使用VC内嵌Python实现的一个代码检测工具
最近组内准备整顿代码,领导让我写个简单的python脚本分析代码中注释的行数和无效注释。因为这个需求不是很急,所以我想把简单的事情做复杂点。于是就写了一个用VC内嵌Python,并通过模拟按键和发消息去控制其他软件的工具。(转载请…
Python如何实现24个微信大群万人同步转发直播?
作者 | 猪哥66来源 | CSDN博客今天我们来学习微信机器人多群转发做同步图文直播!一、背景介绍猪哥一年前在建Python学习群的时候就说过,要邀请企业大佬来学习群做直播。其实文章早就写好了,但是一直没有找到好的转发软件,所以耽搁…

ITSM实施三招[案例]
当前国外成熟的ITSM解决方案的实施成本相对比较高,使一些对成本较敏感的的IT部门,成为ITSM实施的一个真空区。对于国内起步阶段的ITSM(IT服务管理)实施来说,南航的ITSM实施之路是一个借鉴。 南航it环境 在各大航空公司…
lr手工添加关联函数的步骤:
点击“确定”后: 如何修改已经创建好的关联规则:

新闻内容实现分页
/**//// <summary> /// 新闻内容分页 /// </summary> /// <param name"content">新闻内容</param> /// <param name"extension">扩展名(aspx,html..)</param> /// <returns></returns>pub…
使用自己的数据集训练MobileNet、ResNet实现图像分类(TensorFlow)| CSDN博文精选
作者 | pan_jinquan来源 | CSDN博文精选之前写了一篇博客《使用自己的数据集训练GoogLenet InceptionNet V1 V2 V3模型(TensorFlow)》https://panjinquan.blog.csdn.net/article/details/81560537,本博客就是此博客的框架基础上,完…

VC下提前注入进程的一些方法1——远线程不带参数
前些天一直在研究Ring3层的提前注入问题。所谓提前注入,就是在程序代码逻辑还没执行前就注入,这样做一般用于Hook API。(转载请指明出处)自己写了个demo,在此记下。 我的demo使用了两种注入方式:1 远线程&a…

【转】用示例说明索引数据块中出现热块的场景,并给出解决方案
文章转自:http://www.luocs.com/archives/582.html

VC下提前注入进程的一些方法2——远线程带参数
在前一节中介绍了通过远线程不带参数的方式提前注入进程,现在介绍种远线程携带参数的方法。(转载请指明出处) 1.2 执行注入的进程需要传信息给被注入进程 因为同样采用的是远线程注入,所以大致的思路是一样的,只是在细…
芬兰开放“线上AI速成班”课程,全球网民均可免费观看
出品 | AI科技大本营(ID:rgznai100)去年,芬兰推出了一个免费的“人工智能线上速成班”项目,目的是向该国民众教授与新技术有关的知识。现在,作为送给全世界的圣诞节礼物,这个项目已面向全球网民开放访问&am…

deepin开通ssh
1、在终端打入下面命令进行安装sudo apt-get install openssh-server2、启用sshservice ssh start 反馈:start: Rejected send message, 1 matched rules; type"method_call", sender":1.56" (uid1000 pid2272 comm"start ssh ") int…

实现等待窗体的几种方式
实现等待窗体的几种方式:下面说明了五种可以实现等待窗体的方式,其中三种给出了代码。准备资料安全访问控件成员为了保证在创建控件的线程上调用控件成员,用下面的方式封装控件的属性、方法、其他自定义成员的访问。如: winWordControl.LoadD…
GitHub宝藏项目标星1.6w+,编程新手有福了
作者 | Rocky0429来源 | Python空间(ID: Devtogether)特别惭愧的是,虽然我很早就知道 GitHub,但是学会逛 GitHub 的时间特别晚。当时一方面是因为菜,看着这种全是英文的东西难受,不知道该怎么去玩ÿ…

VC下提前注入进程的一些方法3——修改程序入口点
前两节中介绍了通过远线程进行注入的方法。现在换一种方法——修改进程入口点。(转载请指明出处) 在PE文件中,其中有个字段标识程序入口点位置。我们通过这个字段,到达程序入口点。PE文件的结构我这儿不讨论(我会在之后…

如何产生签名applet能让applet能够访问本地资源
2019独角兽企业重金招聘Python工程师标准>>> 如何产生签名applet,以使applet能够访问本地资源? 在jdk1.1中,可以使用javakey命令来产生公钥,私钥,证书和签名的jar文件,详细资料请参考: http://java.sun.com/security/usingJavakey.html而java 2对签名机制做了比较大…

VC提前注入.net软件的方法
在之前几节介绍了各种注入方法,但是这些方法存在一些缺陷——对.net程序注入无效。(转载请指明出处) 这个可以理解,.net程序的代码不是汇编,而是微软自定义的IL中间语言。.net CLR如同虚拟机,解析并执行这些…
活动推荐:语音和语言技术在自然交互中的实践沙龙
智能语音技术已经渗透进家居生活、车载、金融服务等日常生活场景,在很大程度上解放了人们的双手和眼睛,语音交互成为连接人与信息/服务的新入口。根据IDC预测,国内对话式人工智能市场规模将在2022年达到78亿元。如何提供便捷、高效、高可用的…

JS字符串 window.open() window.opener window.name window对象总结
晚上总结了一下,发上来分享:字符串 window.open() window.opener window.name window对象等的一点总结 http://download1.csdn.net/down3/20070614/14012050509.rar