一,线程池的基本组成
1. 工作线程队列
2. 任务队列
3. 线程管理器(封装了线程池的一些基本方法,创建,销毁,加入新任务等)
比如一个常用的网络服务,通常主循环用于处理接收与基本的recv/send操作。可是如果某些业务操作需要长时间的处理数据。
比如等待数据库查询结果,对数据进行编解码等业务逻辑事。为了不让主线程进行长时间的阻塞,从而引入了线程池。让线程池的工作队列来处理具体的业务。
主线程则继续处理网络连接。
应用:线程池是生产者与消费者模型的一个最典型的应用。最常见的nginx服务中就使用了线程池。
二、线程池的基本工作流程
比如主循环是一个服务器,主循环首先处理各种网络IO,当需要实际处理业务数据的情况。将业务数据封装成“task(有些场合也叫消息)",并加入线程池的工作队列中就, 这个过程也叫做”生产“。
线程池中的工作线程会循环取出工作队列中的任务,并进行实际的业务处理,这个过程也叫”消费“。
1. task的定义
比如对于一个任务可以采用以下的方式来定义:
// define the task node
typedef void* (*callback)(void* arg);
struct node_task {
callback func; // call back which will be executed by the worker thread.
void* user_data;
struct node_task* prev; // link to the prv task
struct node_task* next; // link to the next task
};
其中回调函数则是会被工作线程具体调用的函数。
user_data则是传递给回调函数处理的业务数据。
2. 线程队列的定义
// define the work node which will process the task.
struct node_worker {
pthread_t tid; // thread id.
int terminate; // flag to indicate whether the worker would be terminate.
struct _threadPool* pool;
struct node_worker* prev;
struct node_worker* next;
};
线程队列就是一个双向链表数据结构,