线程池的简单实现

来源:互联网 发布:手机淘宝扫一扫 编辑:程序博客网 时间:2024/04/30 03:09

编写一个简单的线程池程序(本人在此郑重声明:本文仅供菜鸟新手参考,大神请单击屏幕左上角那个“X”状按钮,谢谢配合。)

编译环境:viusal C++ 2010

先说一下线程池:这个池子的作用就是减小用于创建和销毁线程的开销,简单的说就是先创建好一队线程(初始状态为挂起),然后有任务的时候就把这些线程唤醒,没任务的时候再挂起,如果任务过多的话就新建一些线程,如果空闲线程过多就销毁线程。
听起来so easy。。是不是有种马上动手实现的冲动。。。但是表急。。
实现的思路:
最开始的思路:
<1>创建两个线程队列:空闲的线程/运行的线程 queue_thread_free/queue_thread_busy
<2>创建任务队列:先到先执行 queue_task
<3>创建执行任务的线程函数: function_task
<4>创建线程池管理的线程函数:function_manage
<5>设置线程阈值:最大线程数 MAX 最小空闲线程 MIN 初始化线程 INIT
(1)初始化线程池:
用windows API中的线程库来创建INIT个线程,初始状态为挂起,添加到queue_thread_free中。
(2)调用线程管理函数:
通过function_manage来调度线程资源,当有queue_task中有任务的时候就将的queue_thread_free中的空闲线程唤醒,获取queue_task中的任务,将线程添加到queue_thread_busy中。
当任务执行完毕后线程自动挂起,然后将起从queue_thread_busy移动到queue_thread_free中,等待下一个任务的到来。
期间如果空闲线程数小于 MIN 就添加线程,如果线程总量达到 MAX 就不能再添加线程,如果空闲线程数超出 INIT ,就销毁部分线程,至于具体的操作根据不同的需求来自己设定。
(3)销毁线程池
你既然能创建就自然有办法销毁喽。。。原谅我这个渣渣的不负责任。。。

然而理想很丰满,现实很骨干,现实给了我无情的一击。。。。
首先有一个问题就是多个线程操作同一队列时候的读取,这个问题好解决,可以设置互斥锁,虽然它被诟病性能低,但也是个方法不。
第二个问题,就是获取线程的运行状态。最开始我还天真的以为,visual C++线程库创建的线程运行完毕后会自动挂起,当我们调用线程退出函数的时候它就乖乖的退出咯!! 然而坑爹的visual线程库给了我无情的一击,在visual自带的线程库中,线程函数执行完毕return后线程会自动销毁。
不过这也木有关系,我不是还有挂起函数吗。。。再次天真的想到。但是现实再次给了我无情的一击,就是你无法判断线程函数到底是运行状态,还是执行完毕。挂起早了,呵呵,容易死锁(因为所有线程都是操作同一个队列,然而当挂起的时候如果没有执行完毕,内存不会释放),挂起晚了,呵呵,该线程已经退出,say goodbye,那挂起还有个卵用啊!!

既然遇到了问题就要解决问题,我们现在的问题就是如何恰到好处把线程给挂起来,不早一秒也不晚一秒。
于是我找啊找,找啊找,最终找到了方法。。方法有两个(我只找到两个,但估计还有别的方法)。

第一个方法:纯技术流
俗话说一力降十会 一虎服九牛,我就是能恰倒好处的把你丫给挂起来,这要用一个重叠IO(也叫做完成端口)。这个东东啊,比线程还复杂,so,我最终放弃了它,原谅我实力有限。有兴趣的朋友可以去尝试一下,网上有实例,但是我看不懂。

第二个方法:投机取巧法
既然你丫执行完毕就会退出,那我就写一个循环,让你丫一直运行(one loop thread),这样你丫就不会自动退出了吧。还有一个问题就是如何判断任务线程的状态。也好办,每一个任务线程绑定一个任务队列(可以用map表存储,map<线程句柄,任务队列>),运行的时候给它的任务队列里添加任务,队列为空就说明它空闲,然后就把它挂起,销毁的时候任务队列和线程一起销毁。
(这是个方法是一位大神告诉我的,虽然他和我同姓,但是真是差距很大啊,同时还要感谢华某某同学)。

但是本人还是倾向与第一种方法,它对资源的占用和消耗要小于第二种。
好了这就是一个技术渣渣写线程池的过程,思路仅供参考,具体实现过程和代码请见下一回。

0 0
原创粉丝点击