一、threadpool.h
/*
主线程往工作队列中插入任务
工作线程通过竞争来取得任务并且执行
必须保证所有客户的请求都是无状态的
因为同一个连接上的不同请求可能会由不同线程处理
*/
#ifndef THREADPOOL_H
#define THREADPOOL_H
#include <list>
#include <cstdio>
#include <exception>
#include <unistd.h>
#include <errno.h>
#include <pthread.h>
#include <signal.h>
#define DEFAULT_TIME 10 /*10s检测一次*/
#define MIN_WAIT_TASK_NUM 10 /*如果queue_size > MIN_WAIT_TASK_NUM 添加新的线程到线程池*/
#define DEFAULT_THREAD_VARY 10 /*每次创建和销毁线程的个数*/
/*线程池类 将其定义为模板类是为了代码复用 模板参数T是任务类*/
template<typename T>
class threadpool
{
public:
/*
参数 thread_number是线程池中线程的数量
max_requests 请求队列中最多允许的等待处理的请求数量
*/
threadpool(int _min_thread_number =2 ,int _max_thread_number = 100, int _max_requests = 10000);
~threadpool();
/*往请求队列中添加任务*/
bool append(T *request);
private:
/*工作线程运行的函数,它不断从工作队列中取出任务并且执行*/
static void* worker(void *arg);
void run();
/*管理线程函数*/
static void* manager(void *arg);
void adjust_thread();
private:
pthread_t *threads; /*描述线程池的数组,其大小为m_thread_number*/
std::list<T*> work_queue; /*请求队列*/
bool stop; /*是否需要结束线程池*/
int max_requests;
/*实现可以变长线程池新增部分*/
pthread_t adjust_tid; /* 存管理线程tid */
int min_thread_number; /* 线程池最小线程数 */
int max_thread_number; /* 线程池最大线程数 */
int live_thread_number; /* 当前存活线程个数 */
int busy_thread_number; /* 忙状态线程个数 */
int wait_exit_thread_number; /* 要销毁的线程个数 */
pthread_mutex_t lock; /* 用于锁住本结构体 */
pthread_mutex_t thread_counter; /* 记录忙状态线程个数de琐 -- busy_thr_num */
pthread_cond_t queue_not_full; /* 当任务队列满时,添加任务的线程阻塞,等待此条件变量 */
pthread_cond_t queue_not_empty; /* 任务队列里不为空时,通知等待任务的线程 */
};
template<typename T>
threadpool<T>::threadpool(int _min_thread_number,int _max_thread_number,int _max_requests)
{
if (_min_thread_number <= 0 || _max_thread_number <=0||_max_requests <= 0 || _min_thread_number >= _max_thread_number) //非法值警告
{
printf("ERROR: Illegal value!!\n");
throw std::exception();
}
min_thread_number = _min_thread_number;
max_thread_number = _max_thread_number;
live_thread_number = _min_thread_number;
busy_thread_number = 0;
wait_exit_thread_number = 0;
max_requests = _max_requests;
stop = false;
/* 初始化互斥琐、条件变量 */
if (pthread_mutex_init(&lock, NULL) != 0
|| pthread_mutex_init(&thread_counter, NULL) != 0
|| pthread_cond_init(&queue_not_empty, NULL) != 0
|| pthread_cond_init(&queue_not_full, NULL) != 0)
{
printf("init the lock or cond fail");
throw std::exception();
}
//按照最大线程数目 动态分配一个描述线程池的数组
threads = new pthread_t[max_thread_number];
if (threads==NULL)
{
printf("ERROR: Fail to create theads[]!!\n ");
throw std::exception();
}
//创建初始线程
for (int i = 0; i < min_thread_number; i++){
printf("create the %dth threads\n", i);
if (pthread_create(threads + i, NULL, worker, this) != 0) { //使用this指针 然后在worker函数中获取该指针并调用动态方法run
printf("ERROR: Fail to create pthreads !!\n");
delete[] threads;
throw std::exception();
}
}
//创建管理者线程
printf("create the adjust_tid threads\n");
if (pthread_create(&adjust_tid, NULL, manager, this) != 0) {
printf("ERROR: Fail to create adjust_tid !!\n");
throw std::exception();
}
}
template<typename T>
threadpool<T>::~threadpool()
{
/*先销毁管理线程*/
pthread_join(adjust_tid, NULL);
/*回收其他线程*/
for (int i = 0; i < live_thread_number; i++) {
pthread_join(threads + i, NULL);
}
delete[] threads;
/*销毁锁*/
pthread_mutex_destroy(&(lock));
pthread_mutex_destroy(&(thread_counter));
pthread_cond_destroy(&(queue_not_empty));
pthread_cond_destroy(&(queue_not_full));
stop = true;
}
template<typename T>
void* threadpool<T>::worker(void *arg) {
threadpool* pool = (threadpool*)arg;
pool->run();
return pool;
}
template<typename T>
bool threadpool<T>::append(T *request) {
pthread_mutex_lock(&lock); //上锁 进入临界区
while (work_queue.size() == max_requests and !stop) { //队列已经满了
pthread_cond_wait(&queue_not_full, &lock); //等待队列非满
}
if (stop) { //如果线程池已经停止运行了 解锁
pthread_mutex_unlock(&lock);
return false;
}
work_queue.push_back(request); //把新的请求放入队列中
pthread_cond_signal(&queue_not_empty); /*添加完任务后,队列不为空,唤醒线程池中 等待处理任务的线程*/
pthread_mutex_unlock(&lock);
return true;
}
template<typename T>
void threadpool<T>::run() {
while (true) {
pthread_mutex_lock(&lock); //上锁 进入临界区
while (work_queue.size() == 0 and !stop) { //队列为空
pthread_cond_wait(&queue_not_empty, &lock); //等待队列非空
/*清除指定数目的空闲线程,如果要结束的线程个数大于0,结束线程*/
if (wait_exit_thread_number > 0) {
wait_exit_thread_number--;
/*如果线程池里线程个数大于最小值时可以结束当前线程*/
if (live_thread_number > min_thread_number) {
live_thread_number--;
pthread_mutex_unlock(&lock);
pthread_exit(NULL);
}
}
}
/*如果指定了true,要关闭线程池里的每个线程,自行退出处理*/
if (stop) {
pthread_mutex_unlock(&lock);
pthread_exit(NULL); /* 线程自行结束 */
}
/*从任务队列里获取任务, 是一个出队操作*/
T* request = work_queue.front(); //获取请求队列队首请求
work_queue.pop_front();
/*通知可以有新的任务添加进来*/
pthread_cond_broadcast(&queue_not_full);
/*任务取出后,立即解 线程池 锁*/
pthread_mutex_unlock(&lock);
/*开始执行任务*/
pthread_mutex_lock(&thread_counter); /*忙状态线程数变量琐*/
busy_thread_number++; /*忙状态线程数+1*/
pthread_mutex_unlock(&thread_counter);
/*处理任务*/
request->process();
/*任务结束*/
pthread_mutex_lock(&thread_counter); /*忙状态线程数变量琐*/
busy_thread_number--; /*忙状态线程数-1*/
pthread_mutex_unlock(&thread_counter);
}
pthread_exit(NULL);
}
template<typename T>
void * threadpool<T>::manager(void *arg)
{
threadpool* pool = (threadpool*)arg;
pool->adjust_thread();
return pool;
}
template<typename T>
void threadpool<T>::adjust_thread() {
while(!stop)
{
sleep(DEFAULT_TIME); /*定时 对线程池管理*/
pthread_mutex_lock(&lock); //上锁 进入临界区
int work_queue_size = work_queue.size(); /* 关注 任务数 */
int live_thr_num = live_thread_number; /* 存活 线程数 */
pthread_mutex_unlock(&lock); //解锁 退出临界区
pthread_mutex_lock(&lock); //上锁 进入临界区
int busy_thr_num = busy_thread_number; /* 忙着的线程数 */
pthread_mutex_unlock(&lock); //解锁 退出临界区
/* 创建新线程 算法: 当前任务数大于最小任务数, 且存活的线程数少于允许最大线程个数时 如:30>=10 && 40<100 */
if (work_queue_size >= MIN_WAIT_TASK_NUM && live_thr_num < max_thread_number) {
pthread_mutex_lock(&lock); //上锁 进入临界区
int add = 0;
/*一次增加 DEFAULT_THREAD 个线程*/
for (int i = 0; i < max_thread_number && add < DEFAULT_THREAD_VARY
&& live_thread_number < max_thread_number; i++) {
/*
pthread_kill(tid, 0) 给这个tid发送一个0
查看这个线程是否存活
没有活着就返回ESRCH
*/
if (threads[i] == 0 || (pthread_kill(threads[i], 0)== ESRCH)) {
pthread_create(threads+i, NULL, worker, this);
add++;
live_thread_number++;
}
}
pthread_mutex_unlock(&lock); //解锁 退出临界区
}
/* 销毁多余的空闲线程 算法:忙线程X2 小于 存活的线程数 且 存活的线程数 大于 最小线程数时*/
if ((busy_thr_num * 2) < live_thr_num && live_thr_num > min_thread_number) {
pthread_mutex_lock(&lock); //上锁 进入临界区
wait_exit_thread_number = DEFAULT_THREAD_VARY; /* 要销毁的线程数 设置为10 */
pthread_mutex_unlock(&lock); //解锁 退出临界区
for (int i = 0; i < DEFAULT_THREAD_VARY; i++) {
/* 通知处在空闲状态的线程, 他们会自行终止*/
pthread_cond_signal(&queue_not_empty);
}
}
}
}
#endif
二、main.cpp
#include <cstdio>
#include <iostream>
#include "threadpool.h"
#include <unistd.h>
using namespace std;
class User
{
public:
void process() {
pthread_t tid = pthread_self();
printf("I am Child thread:%u\n",tid);
}
};
int main()
{
threadpool<User>* pool = NULL;
try
{
pool = new threadpool<User>;
}
catch (...)
{
return 1;
}
User* user = new User[1000];
pthread_t tid = pthread_self();
while (true) {
for (int i = 0; i < 1000; i++)
{
printf("I am Parent thread:%u\n", tid);
pool->append(user + i);
}
}
return 0;
}