一个简单的线程池模型实现
1. 简介
在EPoll通信模型中,我们常常使用如下的处理方法:
就是将触发的事件交给线程去做而EPoll只管接收产生的事件,为了提高效率,我们会使用多线程(因为当事件产生的速度很快,在排队时,我们用多线程去处理,可以加快事件的处理速度),而线程池可以避免程序在响应用户的过程中频繁产生线程创建和销毁,提高程序效率。
2. 基本结构
处理流程:
当任务队列中有线程时,各线程中队列中取任务并执行任务
若任务队列中没有任务,各线程阻塞
若有新任务达到,唤醒一个线程,去处理新到达的任务
3. 相关元素
线程类:Thread 基于-lpthread封装了自己的线程类
(在之前的博文中有提过:http://my.oschina.net/myspaceNUAA/blog/61975)
互斥量:基于pthread_mutex_t的封装,Mutex类,用于对资源的互斥访问
信号量:基于pthread_cond_t的封装,Condition类,用于线程的等待和苏醒(没有资源陷入等待状态, 若有资源到达,要唤醒阻塞线程起来开工)
线程池:就是线程容器,任务队列的存放容器,同时将任务队列中的任务派发给线程去执行
4. 核心代码
4.1. 线程池启动,就要将指定数量的线程创建好
01 | void start() |
02 | { |
03 | for ( int i = 0; i < m_nPoolSize; i++) |
04 | { |
05 | boost::function< void ()> f; |
06 | f = boost::bind(&ThreadPool::runInThread, this ); |
07 | Thread* pTd = new Thread(f,szId); |
08 | m_pThreads.push_back(pTd); |
09 | pTd->start(); |
10 | } |
11 | } |
4.2 将任务交付给线程池:
01 | /********************************************************* |
02 | 函数名:run |
03 | 功能: 向线程池中注入任务,插入到任务队列中 |
04 | 参数: task 运行任务 |
05 | **********************************************************/ |
06 | void run(ThreadPool::Task &task) |
07 | { |
08 | MutexLock mutexLock(m_mutex); |
09 | m_tasks.push_back(task); |
10 | m_cond.notify(); //有新资源,要唤醒一个线程去处理任务 |
11 | } |
4.3 如何将Task派发给各线程去执行
在线程池创建线程时,每个线程的运行函数都是:ThreadPool::runInThread,也就是说,每个线程通过这个函数从任务队列中取任务并执行,新任务到了后在任务队列中排队,那个线程有空,自然会被唤醒去取任务并执行。01 | void runInThread() |
02 | { |
03 | while (m_bRunning) |
04 | { |
05 | if (!m_tasks.empty()) |
06 | { |
07 | ThreadPool::Task task = takeTask(); |
08 | if (task) |
09 | task(); |
10 | } |
11 | } |
12 | } |
5. 测试程序以及测试结果:
01 | #include <iostream> |
02 | #include "ThreadPool.h" |
03 | using namespace std; |
04 | |
05 | void function( int a, int b) |
06 | { |
07 | int sum = a + b; |
08 | cout<< "function: sum is " <<sum<<endl; |
09 | } |
10 | |
11 | int main() |
12 | { |
13 | ThreadPool threadPool(10, "ThreadPool Of Scott" ); |
14 | threadPool.start(); |
15 | |
16 | boost::function< void ()> f; |
17 | for ( int i = 0; i < 20; i++) |
18 | { |
19 | f = boost::bind(function, i, i+1); |
20 | threadPool.run(f); //依次把任务交给线程池 |
21 | } |
22 | |
23 | sleep(1000*60); |
24 | return 0; |
25 | } |
运行结果:
01 | function: sum is 1 |
02 | function: sum is 3 |
03 | function: sum is 5 |
04 | function: sum is 7 |
05 | function: sum is 9 |
06 | function: sum is 11 |
07 | function: sum is 13 |
08 | function: sum is 15 |
09 | function: sum is 17 |
10 | function: sum is 19 |
11 | function: sum is 21 |
12 | function: sum is 23 |
13 | function: sum is 25 |
14 | function: sum is 27 |
15 | function: sum is 29 |
16 | function: sum is 31 |
17 | function: sum is 33 |
18 | function: sum is 35 |
19 | function: sum is 37 |
20 | function: sum is 39 |
注:模型参考自陈硕MUDUO网络通信库