构思阶段:
1. 线程池的概念:
线程池的实现原理是这样的:在应用程序启动之后,就马上创建一定数量的线程,放入空闲的队列中。这些线程都是处于阻塞状态,这些线程只占一点内存,不占用CPU。当任务到来后,线程池将选择一个空闲的线程,将任务传入此线程中运行。当所有的线程都处在处理任务的时候,线程池将自动创建一定的数量的新线程,用于处理更多的任务。执行任务完成之后线程并不退出,而是继续在线程池中等待下一次任务。当大部分线程处于阻塞状态时,线程池将自动销毁一部分的线程,回收系统资源。
2. 线程池的工作机制
2.1 在线程池的编程模式下,任务是提交给整个线程池,而不是直接提交给某个线程,线程池在拿到任务后,就在内部寻找是否有空闲的线程,如果有,则将任务交给某个空闲的线程。
2.2 一个线程同时只能执行一个任务,但可以同时向一个线程池提交多个任务。
2.3 如果所有的线程都处于工作状态,就添加到队列,进行排队。
2.4 如果队列中的任务个数大于队列的所能容纳的最大数量,那就不能添加任务到队列中,只能等待队列不满才能添加任务到队列中。
代码:
//threadpool.h
#ifndef THREADPOOL_H
#define THREADPOOL_H
#include<iostream>
#include<pthread.h>
#include<cstdlib>
#include<cassert>
#include<cstdio>
#include<deque>
using namespace std;
struct Job
{
void* (*doJobFun)(void *arg); //线程回调函数
void *arg; //回调函数参数
};
class ThreadPool
{
unsigned int threadNum; //线程池中开启线程的个数
unsigned int maxJobNum; //队列中最大job的个数
deque<Job> jobQueue; //任务队列
pthread_t *pthreads; //线程池中所有线程的pthread_t
pthread_mutex_t mutex; //互斥信号量
pthread_cond_t condQueueEmpty; //队列为空的条件变量
pthread_cond_t condQueueFull; //队列为满的条件变量
bool isPoolClose; //线程池是否已经关闭
public:
ThreadPool(int threadNum=10, int maxJobNum=100);
int addJob(Job job);
int destroy();
~ThreadPool();
friend void* run(void* arg);
};
#endif
//threadpool.cpp
#include"threadpool.h"
void* run(void* arg)
{
ThreadPool *pool = (ThreadPool *)arg;
struct Job job ;
while (1) //死循环
{
pthread_mutex_lock(&(pool->mutex));
if (pool->isPoolClose) //线程池关闭,线程就退出
{
pthread_mutex_unlock(&(pool->mutex));
pthread_exit(NULL);
}
while ((pool->jobQueue.empty())) //队列为空时,就等待队列非空
{
//printf("job queue is empty.....\n");
pthread_cond_wait(&(pool->condQueueEmpty), &(pool->mutex));
if (pool->isPoolClose) //线程池关闭,线程就退出
{
pthread_mutex_unlock(&(pool->mutex));
pthread_exit(NULL);
}
}
job=pool->jobQueue.front();
pool->jobQueue.pop_front();
//printf("get job %d,size:%d\n",(int)job.arg,pool->jobQueue.size());
if (pool->jobQueue.size() == (pool->maxJobNum-1))
{
pthread_cond_broadcast(&(pool->condQueueFull)); //队列非满,就可以通知threadpool_add_job函数,添加新任务
}
pthread_mutex_unlock(&(pool->mutex));
(*(job.doJobFun))(job.arg); //线程真正要做的工作,回调函数的调用
}
}
ThreadPool::ThreadPool(int threadNum, int maxJobNum)
{
this->threadNum = threadNum;
this->maxJobNum = maxJobNum;
if (pthread_mutex_init(&(this->mutex), NULL))
{
perror("pthread_mutex_init");
exit(1);
}
if (pthread_cond_init(&(this->condQueueEmpty), NULL))
{
perror("pthread_cond_init");
exit(1);
}
if (pthread_cond_init(&(this->condQueueFull), NULL))
{
perror("pthread_cond_init");
exit(1);
}
this->pthreads = (pthread_t *)malloc(sizeof(pthread_t) * this->threadNum);
if (NULL == this->pthreads)
{
perror("pthreads malloc");
exit(1);
}
this->isPoolClose = false;
unsigned int i;
for (i = 0; i < this->threadNum; ++i)
{
pthread_create(&(this->pthreads[i]), NULL, run, (void *)this);
}
}
int ThreadPool::addJob(Job job)
{
assert(job.doJobFun != NULL);
//assert(job.arg != NULL);
if (this->isPoolClose) //线程池关闭,线程就退出
{
return -1;
}
pthread_mutex_lock(&(this->mutex));
while ((this->jobQueue.size() == this->maxJobNum))
{
//printf("job queue is full\n");
pthread_cond_wait(&(this->condQueueFull), &(this->mutex)); //队列满的时候就等待
}
if (this->isPoolClose) //队列关闭或者线程池关闭就退出
{
pthread_mutex_unlock(&(this->mutex));
return -1;
}
if (this->jobQueue.empty())
{
this->jobQueue.push_back(job);
pthread_cond_broadcast(&(this->condQueueEmpty)); //队列空的时候,有任务来时就通知线程池中的线程:队列非空
}
else
{
this->jobQueue.push_back(job);
}
//printf("add a job:%d,size:%d\n",(int)job.arg,this->jobQueue.size());
pthread_mutex_unlock(&(this->mutex));
return 0;
}
int ThreadPool::destroy()
{
//printf("begin destroy...\n");
pthread_mutex_lock(&(this->mutex));
this->isPoolClose = true; //置队列关闭标志
this->jobQueue.clear();
pthread_mutex_unlock(&(this->mutex));
pthread_cond_broadcast(&(this->condQueueEmpty)); //唤醒线程池中正在阻塞的线程
pthread_cond_broadcast(&(this->condQueueFull)); //唤醒添加任务的threadpool_add_job函数
unsigned int i;
for (i = 0; i < this->threadNum; ++i)
{
pthread_join(this->pthreads[i], NULL); //等待线程池的所有线程执行完毕
//printf("thread %X exit.\n",(unsigned int)this->pthreads[i]);
}
pthread_mutex_destroy(&(this->mutex)); //清理资源
pthread_cond_destroy(&(this->condQueueEmpty));
pthread_cond_destroy(&(this->condQueueFull));
free(this->pthreads);
//printf("end destroy...\n");
return 0;
}
ThreadPool::~ThreadPool()
{
//destroy();
}