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. 线程池启动,就要将指定数量的线程创建好
void start()
{
for (int i = 0; i < m_nPoolSize; i++)
{
boost::function f;
f = boost::bind(&ThreadPool::runInThread, this);
Thread* pTd = new Thread(f,szId);
m_pThreads.push_back(pTd);
pTd->start();
}
}
4.2 将任务交付给线程池:
/*********************************************************
函数名:run
功能: 向线程池中注入任务,插入到任务队列中
参数: task 运行任务
**********************************************************/
void run(ThreadPool::Task &task)
{
MutexLock mutexLock(m_mutex);
m_tasks.push_back(task);
m_cond.notify(); //有新资源,要唤醒一个线程去处理任务
}
4.3 如何将Task派发给各线程去执行
在线程池创建线程时,每个线程的运行函数都是:ThreadPool::runInThread,也就是说,每个线程通过这个函数从任务队列中取任务并执行,新任务到了后在任务队列中排队,那个线程有空,自然会被唤醒去取任务并执行。
void runInThread()
{
while(m_bRunning)
{
if (!m_tasks.empty())
{
ThreadPool::Task task = takeTask();
if (task)
task();
}
}
}
5. 测试程序以及测试结果:
#include
#include "ThreadPool.h"
using namespace std;
void function(int a, int b)
{
int sum = a + b;
cout<<"function: sum is "< f;
for (int i = 0; i < 20; i++)
{
f = boost::bind(function, i, i+1);
threadPool.run(f); //依次把任务交给线程池
}
sleep(1000*60);
return 0;
}
运行结果:
function: sum is 1
function: sum is 3
function: sum is 5
function: sum is 7
function: sum is 9
function: sum is 11
function: sum is 13
function: sum is 15
function: sum is 17
function: sum is 19
function: sum is 21
function: sum is 23
function: sum is 25
function: sum is 27
function: sum is 29
function: sum is 31
function: sum is 33
function: sum is 35
function: sum is 37
function: sum is 39
注:模型参考自陈硕MUDUO网络通信库