线程池的书写
1.pthread_create函数:创建线程
头文件:#include
int pthread_create(pthread_t *thread, const pthread_attr_t *attr,
void *(*start_routine) (void *), void *arg);
pthread_t *thread:传递一个pthread_t变量地址进来,用于保存新线程的tid(线程ID)
const pthread_attr_t *attr:线程属性设置,如使用默认属性,则传NULL
void *(*start_routine) (void *):函数指针,指向新线程应该加载执行的函数模块
void *arg:指定线程将要加载调用的那个函数的参数
返回值:成功返回0,失败返回错误号。
2.pthread_self函数:获取调用线程tid
头文件:#include
pthread_t pthread_self(void);
3.pthread_exit函数:调用线程退出函数
void pthread_exit(void *retval);
void *retval:线程退出时传递出的参数,可以是退出值或地址,如是地址时,不能是线程内部申请的局部地址。
注意和exit函数的区别,任何线程里exit导致进程退出,其他线程
未工作结束,主控线程退出时不能return或exit。
4.pthread_join函数:阻塞退出,回收尸体
int pthread_join(pthread_t thread, void **retval);
pthread_t thread:回收线程的tid
void **retval:接收退出线程传递出的返回值
返回值:成功返回0,失败返回错误号
5.pthread_cancel函数:在进程内某个线程可以取消另一个线程。
int pthread_cancel(pthread_t thread);
被取消的线程,退出值,定义在Linux的pthread库中常数PTHREAD_CANCELED的值是-1。
可以在头文件pthread.h中找到它的定义:
#define PTHREAD_CANCELED ((void *) -1)
6.pthread_detach函数:自己杀自己然后自己收尸
int pthread_detach(pthread_t tid);
pthread_t tid:分离线程tid
返回值:成功返回0,失败返回错误号
但是线程也可以被置为detach状态,这样的线程一旦终止就立刻回收,它占用的所有资源,而不保留终止状态。不能对一个已经处于detach状态的线程调用pthread_join。
8.线程基类的封装
#ifndef BASETHREAD_H
#define BASETHREAD_H
#include
#include
#include
class CBaseThread
{
public:
CBaseThread();
~CBaseThread();
void start();
virtual int run() = 0;
bool isRunning() const;
pthread_t threadId() const;
protected:
pthread_t m_tid;
bool m_bRun;
private:
static void * rontine(void *arg);
};
#endif // BASETHREAD_H
.cpp
#include "BaseThread.h"
CBaseThread::CBaseThread()
:m_tid(0), m_bRun(false)
{
}
CBaseThread::~CBaseThread()
{
}
void CBaseThread::start()
{
if (m_bRun == false)
{
if( pthread_create(&m_tid,NULL,rontine,(void *)this) != 0)
{
perror("create thread error : ");
}
}
}
bool CBaseThread::isRunning() const
{
return m_bRun;
}
void * CBaseThread::rontine(void *arg)
{
pthread_detach(pthread_self());
CBaseThread *thr = (CBaseThread *)arg;
thr->m_bRun = true;
int ret = thr->run();
thr->m_bRun = false;
pthread_exit((void *)ret);
}
#ifndef _THREADPOOL_H_
#define _THREADPOOL_H_
#include
#include
#include
#include
#include
#include
#include
using namespace std;
//任务基类,其他任务都是继承它
class CTask
{
public:
CTask(){}
~CTask(){}
virtual int run()= 0;
};
//线程池类
class CThreadPool
{
public:
CThreadPool(int maxCount = 100, int waittime = 60);
int start(int threadcount = 10);
int addTask(CTask *task); //把任务添加到线程池中
int destroy(); //停止线程池
protected:
static void* rontine(void * threadData); //新线程的线程函数
private:
void createThread();
void lock(); //互斥量上锁
void unlock(); //互斥量解锁
int wait(); //设置条件变量永久等待
int waittime(int sec); //设置条件变量等待时间
int signal(); //发送信号
int broadcast(); //广播所有线程信号
list m_taskList; //任务列表
pthread_mutex_t m_mutex; //线程同步锁
pthread_cond_t m_cond; //线程同步的条件变量
bool m_bStop; //线程停止标识
int m_maxCount; //线程的最大限制
int m_waitCount; //线程等待数
int m_count;
int m_waittime;
};
.cpp
#include "ThreadPool.h"
CThreadPool::CThreadPool(int maxCount, int waittime)
{
//设置最大线程数量
m_maxCount = maxCount;
if (m_maxCount <= 0)
{
printf("[threadpool] thread max count error \n");
exit(-1);
}
m_bStop = false;
m_waitCount = 0;
m_count = 0;
m_waittime = waittime;
if (m_waittime <= 0)
{
printf("[threadpool] thread wait time error \n");
exit(-1);
}
//初始化互斥量和条件变量
pthread_mutex_init(&m_mutex, NULL);
pthread_cond_init(&m_cond, NULL);
}
void CThreadPool::lock()
{
//互斥量加锁
if( pthread_mutex_lock(&m_mutex) != 0)
perror("Lock error");
//printf("L\n");
}
void CThreadPool::unlock()
{
//互斥量解锁
if( pthread_mutex_unlock(&m_mutex) != 0)
perror("Unlock error");
//printf("U\n");
}
int CThreadPool::wait()
{
//设置添加变量等待
//条件变量等待一定要在互斥锁区域内
//lock();
int ret = pthread_cond_wait(&m_cond, &m_mutex);
//unlock();
return ret;
}
int CThreadPool::waittime(int sec)
{
//设置添加变量等待时间sec秒
//条件变量等待一定要在互斥锁区域内
//lock();
struct timespec abstime;
clock_gettime(CLOCK_REALTIME, &abstime);
abstime.tv_sec += sec;
int ret = pthread_cond_timedwait(&m_cond, &m_mutex, &abstime);
//unlock();
return ret;
}
int CThreadPool::signal()
{
//发送条件变量信号
return pthread_cond_signal(&m_cond);
}
int CThreadPool::broadcast()
{
//广播条件变量信号
return pthread_cond_broadcast(&m_cond);
}
int CThreadPool::start(int threadcount)
{
if (threadcount <= 0)
{
printf("create thread count error\n");
return -1;
}
threadcount = threadcount > m_maxCount ? m_maxCount : threadcount;
lock();
for (int i = 0; i < threadcount; i++)
createThread();
unlock();
return 0;
}
void CThreadPool::createThread()
{
//如果没有线程等待,并且线程的数量小于最大数,线程池不是停止
if( m_count < m_maxCount && !m_bStop)
{
pthread_t tid = 0;
if( pthread_create(&tid, NULL, rontine, (void *)this) != 0)
{
perror("create thread error : ");
//printf("current thread count %d max count %d\n", m_count, m_maxCount);
}
else
{
//printf("create thread id 0x%x\n",tid);
m_count++;
}
}
}
//线程池线程运行函数
void* CThreadPool::rontine(void * threadData)
{
CThreadPool *pool = (CThreadPool *)threadData;
while(1)
{
pool->lock();
if (pool->m_bStop)
{
//线程池停止,线程退出,线程id从列表中移出
break;
}
//如果没有任务,线程进入等待状态
if (pool->m_taskList.size() == 0)
{
//等待的线程计数加一
pool->m_waitCount++;
int ret = pool->waittime(pool->m_waittime);
//线程被唤醒,等待的线程计数减一
pool->m_waitCount--;
//判断是否是等待超时
if (ret == ETIMEDOUT)
{
break;
}
}
//如果有任务
if (pool->m_taskList.size() > 0)
{
//获取任务
CTask *task = pool->m_taskList.front();
pool->m_taskList.pop_front();
//cout << "current task count : " << pool->m_taskList.size() << endl;
pool->unlock();
//要在运行任务之前解锁,以免锁被占用
task->run();
delete task;
//pool->lock();
}
else
{
pool->unlock();
}
}
//cout<< "thread exit" << endl;
pool->m_count--;
//printf("thread count %d task count %d\n", pool->m_count, pool->m_taskList.size());
if (pool->m_count <= 0 && pool->m_bStop )
{
pool->signal();
}
pool->unlock();
pthread_exit(NULL);
//return NULL;
}
int CThreadPool::addTask(CTask *task)
{
//判断线程池是否已经停止
lock();
if ( !m_bStop )
{
m_taskList.push_back(task);
}
else
{
unlock();
return -1;
}
//如果有线程在等待,发送信号唤醒一个线程去处理
if (m_waitCount > 0)
{
signal();
}
else
{
createThread();
}
unlock();
return 0;
}
int CThreadPool::destroy()
{
//设置退出标识为true
m_bStop = true;
//清空任务列表
lock();
list::iterator it = m_taskList.begin();
for (; it != m_taskList.end(); it++)
{
CTask *task = *it;
delete task;
task = NULL;
}
m_taskList.clear();
unlock();
//广播信号,然后等待的线程解除阻塞
broadcast();
//sleep(1);
wait();
return 0;
}