本文章主要介绍线程池的定义,作用,原理,以及实现一个线程池组件。
池化组件主要用来作为应用程序的资源(数据库请求资源,内存分配资源,线程池创建等)的缓冲器,提高响应,避免频繁与第三方服务器以及操作系统操作,而是 程序启动时候,一次性分配,然后再跟进业务并发量需求来进行缩放。
1 线程池在高性能服务器使用的大体位置:
对于高性能服务器而言,底层网路组件常用epoll处理接收io数据;而每个fd对于的接收,解析,发送处理
2 使用场景:
线程池操作的常见的任务:a:写日志 b:计算结果(业务)时间较长的 c:crud数据库操作增删改查
3 线程池定义与组成
组成包括三部分:任务队列 (记录日志,crud等达成的任务集合),执行队列 (线程集合),管理组件 (管理协调任务队列与执行队列有序工作)
组成图如下:
4 多线程网络框架(高性能服务器)
常说的多线程网络框架是指将检查io, 读写io, 解析数据 三个内容将那些放在线程池中,不同的放发就有不同的实现形式。
不管什么服务器网络层网络数据的处理,每一帧网络数据处理的流程都是三个阶段:
1 检测IO事件是否就绪:epoll处理
2 对IO进行读写操作:recv/send
3 对数据进行解析与操作:parser
4.1 粗略图:
4.2 伪代码流程:
int push_tasks(void *task){
} //往线程池中抛入任务
void eventLoop(){
while(1){
int nReady = epoll_wait(); //epoll检测
for(int i = 0; i < nReady; i++){
#if0 //方案一:单线程
recv(fd, buffer, length, 0);
parse();
send();
#elseif0 //方案二:将每个任务都抛入线程池中(读写以及解析全部放在线程池中)
task = fd;
push_task(tasks);
#else //方案三:将接收数据放在时间循环中,而只是将接收到的buffer传入线程池,而不是整个任务在线程池中做解析
recv(fd, buffer, length, 0);
push_back(buffer);
#endif
}
}
}
对于不同的方法有不同的方案他们的优缺点进行比较
方案一:单线程:
优点:此方案适用无日志,db操作。纯内存式操作是OK的。
缺点:如果parser解析引入日志,db操作,就不适用,非常耗时。
方案二:读写以及解析全部放在线程池处理:
此方案优点:主循环是最快的&#