线程池
来源:互联网 发布:网络硬盘播放器怎么用 编辑:程序博客网 时间:2024/05/19 00:10
但是在一些web、email、database等应用里,比如彩铃,我们的应用在任何时候都要准备应对数目巨大的连接请求,同时,这些请求所要完成的任务却又可能非常的简单,即只占用很少的处理时间。这时,我们的应用有可能处于不停的创建线程并销毁线程的状态。虽说比起进程的创建,线程的创建时间已经大大缩短,但是如果需要频繁的创建线程,并且每个线程所占用的处理时间又非常简短,则线程创建和销毁带给处理器的额外负担也是很可观的。
线程池的作用正是在这种情况下有效的降低频繁创建销毁线程所带来的额外开销。一般来说,线程池都是采用预创建的技术,在应用启动之初便预先创建一定数目的线程。应用在运行的过程中,需要时可以从这些线程所组成的线程池里申请分配一个空闲的线程,来执行一定的任务,任务完成后,并不是将线程销毁,而是将它返还给线程池,由线程池自行管理。如果线程池中预先分配的线程已经全部分配完毕,但此时又有新的任务请求,则线程池会动态的创建新的线程去适应这个请求。当然,有可能,某些时段应用并不需要执行很多的任务,导致了线程池中的线程大多处于空闲的状态,为了节省系统资源,线程池就需要动态的销毁其中的一部分空闲线程。因此,线程池都需要一个管理者,按照一定的要求去动态的维护其中线程的数目。
基于上面的技术,线程池将频繁创建和销毁线程所带来的开销分摊到了每个具体执行的任务上,执行的次数越多,则分摊到每个任务上的开销就越小。
当然,如果线程创建销毁所带来的开销与线程执行任务的开销相比微不足道,可以忽略不计,则线程池并没有使用的必要。比如,FTP、Telnet等应用时。
线程池适用情况:
单位时间内处理数目巨大的连接请求,但处理时间相对较短。主要特点就是使用与创建技术,将线程创建和销毁本身带来的开销分摊到具体任务上,任务执行次数越多,则节省时间越多。再有一个就是线程池采用与创建技术创建的线程池规模一般有一个上界,可以解决一些服务器无法同时创建一定量数目线程的问题。线程池将与线程执行相关的任务进行了高层次的抽象,使之与具体的执行任务无关。另外该线程池具有动态伸缩性,它能根据执行任务的轻重自动调整线程池中线程的数量.(除了使用waitxxx也可以手动挂起启动线程来实现,不过这样就比较麻烦了,以为我们还是要设置一个管理线程来监听事件的发生然后对线程池中各个线程的状态进行调整,还不如让线程池中线程来直接监听等待事件等对象的到来)。如果我们需要处理的是一个长连接,即个连接上都是一个执行时间很长的任务,甚至就是一个不会停止的任务,这样我们就没有必要使用线程池技术。而是直接采取“即时创建、即时销毁”的策略就可以了。这就是所说的我们要根据实际的需求状况设计不同的解决方案。
代码一
//win32线程池代码(WinApi/C++)//健壮, 高效,易用,易于扩, 可用于任何C++编译器 //说明, 这段代码我用了很久, 我删除了自动调整规模的代码(因为他还不成熟)/******************************************************************* Thread Pool For Win32 * VC++ 6, BC++ 5.5(Free), GCC(Free)* Update : 2004.6.9 llBird wushaojian@21cn.comUse:1):void threadfunc(void *p){ //...} ThreadPool tp; for(i=0; i<100; i++) tp.Call(threadfunc); ThreadPool tp(20);//20为初始线程池规模 tp.Call(threadfunc, lpPara); tp.AdjustSize(50);//增加50 tp.AdjustSize(-30);//减少302):class MyThreadJob : public ThreadJob //线程对象从ThreadJob扩展{public: virtual void DoJob(void *p)//自定义的虚函数 { //.... }}; MyThreadJob mt[10]; ThreadPool tp; for(i=0; i<100 i++) tp.Call(mt + i);//tp.Call(mt + i, para);*******************************************************************/#ifndef _ThreadPool_H_#define _ThreadPool_H_#pragma warning(disable: 4530)#pragma warning(disable: 4786)#include <cassert>#include <vector>#include <queue>#include <windows.h>class ThreadJob //工作基类{public: //供线程池调用的虚函数 virtual void DoJob(void *pPara) = 0;};class ThreadPool{protected://用户对象结构struct CallProcPara {ThreadJob* _pObj;//用户对象 void *_pPara;//用户参数CallProcPara(ThreadJob* p, void *pPara) : _pObj(p), _pPara(pPara) { };};//用户函数结构struct JobItem {void (*_pFunc)(void *);//函数void *_pPara; //参数JobItem(void (*pFunc)(void *) = NULL, void *pPara = NULL) : _pFunc(pFunc), _pPara(pPara) { };};//线程池中的线程结构struct ThreadItem{HANDLE _Handle; //线程句柄ThreadPool *_pThis; //线程池的指针DWORD _dwLastBeginTime; //最后一次运行开始时间DWORD _dwCount; //运行次数bool _fIsRunning;ThreadItem(ThreadPool *pthis) : _pThis(pthis), _Handle(NULL), _dwLastBeginTime(0), _dwCount(0), _fIsRunning(false) { };~ThreadItem(){if(_Handle){CloseHandle(_Handle);_Handle = NULL;}}};std::queue<JobItem *> _JobQueue; //工作队列std::vector<ThreadItem *> _ThreadVector; //线程数据CRITICAL_SECTION _csThreadVector, _csWorkQueue; //工作队列临界, 线程数据临界HANDLE _EventEnd, _EventComplete, _SemaphoreCall, _SemaphoreDel;//结束通知, 完成事件, 工作信号, 删除线程信号long _lThreadNum, _lRunningNum; //线程数, 运行的线程数public: //dwNum 线程池规模 ThreadPool(DWORD dwNum = 4) : _lThreadNum(0), _lRunningNum(0) { InitializeCriticalSection(&_csThreadVector); InitializeCriticalSection(&_csWorkQueue); _EventComplete = CreateEvent(0, false, false, NULL); _EventEnd = CreateEvent(0, true, false, NULL); _SemaphoreCall = CreateSemaphore(0, 0, 0x7FFFFFFF, NULL); _SemaphoreDel = CreateSemaphore(0, 0, 0x7FFFFFFF, NULL); assert(_SemaphoreCall != INVALID_HANDLE_VALUE); assert(_EventComplete != INVALID_HANDLE_VALUE); assert(_EventEnd != INVALID_HANDLE_VALUE); assert(_SemaphoreDel != INVALID_HANDLE_VALUE); AdjustSize(dwNum <= 0 ? 4 : dwNum); } ~ThreadPool() { DeleteCriticalSection(&_csWorkQueue); CloseHandle(_EventEnd); CloseHandle(_EventComplete); CloseHandle(_SemaphoreCall); CloseHandle(_SemaphoreDel); std::vector<ThreadItem*>::iterator iter; for(iter = _ThreadVector.begin(); iter != _ThreadVector.end(); iter++) { if(*iter) delete *iter; } DeleteCriticalSection(&_csThreadVector); } //调整线程池规模 int AdjustSize(int iNum) { if(iNum > 0) { ThreadItem *pNew; EnterCriticalSection(&_csThreadVector); for(int _i=0; _i<iNum; _i++) {_ThreadVector.push_back(pNew = new ThreadItem(this)); assert(pNew);pNew->_Handle = CreateThread(NULL, 0, DefaultJobProc, pNew, 0, NULL);assert(pNew->_Handle); } LeaveCriticalSection(&_csThreadVector); } else { iNum *= -1; ReleaseSemaphore(_SemaphoreDel, iNum > _lThreadNum ? _lThreadNum : iNum, NULL); } return (int)_lThreadNum; } //调用线程池 void Call(void (*pFunc)(void *), void *pPara = NULL) { assert(pFunc); EnterCriticalSection(&_csWorkQueue); _JobQueue.push(new JobItem(pFunc, pPara)); LeaveCriticalSection(&_csWorkQueue); ReleaseSemaphore(_SemaphoreCall, 1, NULL); } //调用线程池 inline void Call(ThreadJob * p, void *pPara = NULL) {Call(CallProc, new CallProcPara(p, pPara)); } //结束线程池, 并同步等待 bool EndAndWait(DWORD dwWaitTime = INFINITE) { SetEvent(_EventEnd); return WaitForSingleObject(_EventComplete, dwWaitTime) == WAIT_OBJECT_0; } //结束线程池 inline void End() {SetEvent(_EventEnd); } inline DWORD Size() {return (DWORD)_lThreadNum; } inline DWORD GetRunningSize() {return (DWORD)_lRunningNum; } bool IsRunning() {return _lRunningNum > 0; }protected://调用用户对象虚函数static void CallProc(void *pPara) {CallProcPara *cp = static_cast<CallProcPara *>(pPara);assert(cp);if(cp){cp->_pObj->DoJob(cp->_pPara);delete cp;}}//工作线程static DWORD WINAPI DefaultJobProc(LPVOID lpParameter = NULL){ ThreadItem *pThread = static_cast<ThreadItem*>(lpParameter); assert(pThread); ThreadPool *pThreadPoolObj = pThread->_pThis; assert(pThreadPoolObj); InterlockedIncrement(&pThreadPoolObj->_lThreadNum); HANDLE hWaitHandle[3]; hWaitHandle[0] = pThreadPoolObj->_SemaphoreCall; hWaitHandle[1] = pThreadPoolObj->_SemaphoreDel; hWaitHandle[2] = pThreadPoolObj->_EventEnd; JobItem *pJob; bool fHasJob; for(;;) { DWORD wr = WaitForMultipleObjects(3, hWaitHandle, false, INFINITE); //响应删除线程信号 if(wr == WAIT_OBJECT_0 + 1) break; //从队列里取得用户作业 EnterCriticalSection(&pThreadPoolObj->_csWorkQueue); if(fHasJob = !pThreadPoolObj->_JobQueue.empty()) { pJob = pThreadPoolObj->_JobQueue.front(); pThreadPoolObj->_JobQueue.pop(); assert(pJob); } LeaveCriticalSection(&pThreadPoolObj->_csWorkQueue); //受到结束线程信号 确定是否结束线程(结束线程信号 && 是否还有工作) if(wr == WAIT_OBJECT_0 + 2 && !fHasJob) break; if(fHasJob && pJob) { InterlockedIncrement(&pThreadPoolObj->_lRunningNum); pThread->_dwLastBeginTime = GetTickCount(); pThread->_dwCount++; pThread->_fIsRunning = true; pJob->_pFunc(pJob->_pPara); //运行用户作业 delete pJob; pThread->_fIsRunning = false; InterlockedDecrement(&pThreadPoolObj->_lRunningNum); }} //删除自身结构 EnterCriticalSection(&pThreadPoolObj->_csThreadVector); pThreadPoolObj->_ThreadVector.erase(find(pThreadPoolObj->_ThreadVector.begin(), pThreadPoolObj->_ThreadVector.end(), pThread)); LeaveCriticalSection(&pThreadPoolObj->_csThreadVector); delete pThread; InterlockedDecrement(&pThreadPoolObj->_lThreadNum); if(!pThreadPoolObj->_lThreadNum) //所有线程结束 SetEvent(pThreadPoolObj->_EventComplete); return 0; }};#endif //_ThreadPool_H_
代码二
commondef.h
//单位秒,监测空闲列表时间间隔,在空闲队列中超过TASK_DESTROY_INTERVAL时间的任务将被自动销毁const int CHECK_IDLE_TASK_INTERVAL = 300;//单位秒,任务自动销毁时间间隔const int TASK_DESTROY_INTERVAL = 60; //监控线程池是否为空时间间隔,微秒const int IDLE_CHECK_POLL_EMPTY = 500;//线程池线程空闲自动退出时间间隔 ,5分钟const int THREAD_WAIT_TIME_OUT = 300;taskpool.cpp
#include "taskpool.h"#include <string.h>#include <stdio.h>#include <pthread.h> TaskPool::TaskPool(const int & poolMaxSize) : m_poolSize(poolMaxSize) , m_taskListSize(0) , m_bStop(false){ pthread_mutex_init(&m_lock, NULL); pthread_mutex_init(&m_idleMutex, NULL); pthread_cond_init(&m_idleCond, NULL); pthread_attr_t attr; pthread_attr_init( &attr ); pthread_attr_setdetachstate( &attr, PTHREAD_CREATE_JOINABLE ); // 让线程独立运行 pthread_create(&m_idleId, &attr, CheckIdleTask, this); //创建监测空闲任务进程 pthread_attr_destroy(&attr);}TaskPool::~TaskPool(){ if(!m_bStop) { StopPool(); } if(!m_taskList.empty()) { std::list<Task*>::iterator it = m_taskList.begin(); for(; it != m_taskList.end(); ++it) { if(*it != NULL) { delete *it; *it = NULL; } } m_taskList.clear(); m_taskListSize = 0; } if(!m_idleList.empty()) { std::list<Task*>::iterator it = m_idleList.begin(); for(; it != m_idleList.end(); ++it) { if(*it != NULL) { delete *it; *it = NULL; } } m_idleList.clear(); } pthread_mutex_destroy(&m_lock); pthread_mutex_destroy(&m_idleMutex); pthread_cond_destroy(&m_idleCond);}void * TaskPool::CheckIdleTask(void * arg){ TaskPool * pool = (TaskPool*)arg; while(1) { pool->LockIdle(); pool->RemoveIdleTask(); if(pool->GetStop()) { pool->UnlockIdle(); break; } pool->CheckIdleWait(); pool->UnlockIdle(); }}void TaskPool::StopPool(){ m_bStop = true; LockIdle(); pthread_cond_signal(&m_idleCond); //防止监控线程正在等待,而引起无法退出的问题 UnlockIdle(); pthread_join(m_idleId, NULL);}bool TaskPool::GetStop(){ return m_bStop;}void TaskPool::CheckIdleWait(){ struct timespec timeout; memset(&timeout, 0, sizeof(timeout)); timeout.tv_sec = time(0) + CHECK_IDLE_TASK_INTERVAL; timeout.tv_nsec = 0; pthread_cond_timedwait(&m_idleCond, &m_idleMutex, &timeout);}int TaskPool::RemoveIdleTask(){ int iRet = 0; std::list<Task*>::iterator it, next; std::list<Task*>::reverse_iterator rit = m_idleList.rbegin(); time_t curTime = time(0); for(; rit != m_idleList.rend(); ) { it = --rit.base(); if(difftime(curTime,((*it)->last_time)) >= TASK_DESTROY_INTERVAL) { iRet++; delete *it; *it = NULL; next = m_idleList.erase(it); rit = std::list<Task*>::reverse_iterator(next); } else { break; } }}int TaskPool::AddTask(task_fun fun, void *arg){ int iRet = 0; if(0 != fun) { pthread_mutex_lock(&m_lock); if(m_taskListSize >= m_poolSize) { pthread_mutex_unlock(&m_lock); iRet = -1; //task pool is full; } else { pthread_mutex_unlock(&m_lock); Task * task = GetIdleTask(); if(NULL == task) { task = new Task; } if(NULL == task) { iRet = -2; // new failed } else { task->fun = fun; task->data = arg; pthread_mutex_lock(&m_lock); m_taskList.push_back(task); ++m_taskListSize; pthread_mutex_unlock(&m_lock); } } } return iRet;}Task* TaskPool::GetTask(){ Task *task = NULL; pthread_mutex_lock(&m_lock); if(!m_taskList.empty()) { task = m_taskList.front(); m_taskList.pop_front(); --m_taskListSize; } pthread_mutex_unlock(&m_lock); return task;}void TaskPool::LockIdle(){ pthread_mutex_lock(&m_idleMutex);}void TaskPool::UnlockIdle(){ pthread_mutex_unlock(&m_idleMutex);}Task * TaskPool::GetIdleTask(){ LockIdle(); Task * task = NULL; if(!m_idleList.empty()) { task = m_idleList.front(); m_idleList.pop_front(); } UnlockIdle(); return task;}void TaskPool::SaveIdleTask(Task*task){ if(NULL != task) { task->fun = 0; task->data = NULL; task->last_time = time(0); LockIdle(); m_idleList.push_front(task); UnlockIdle(); }}
taskpool.h
#ifndef TASKPOOL_H#define TASKPOOL_H/* purpose @ 任务池,主要是缓冲外部高并发任务数,有manager负责调度任务 * 任务池可自动销毁长时间空闲的Task对象 * 可通过CHECK_IDLE_TASK_INTERVAL设置检查idle空闲进程轮训等待时间 * TASK_DESTROY_INTERVAL 设置Task空闲时间,超过这个时间值将会被CheckIdleTask线程销毁 * date @ 2013.12.23 * author @ haibin.wang */#include <list>#include <pthread.h>#include "commondef.h"//所有的用户操作为一个task,typedef void (*task_fun)(void *);struct Task{ task_fun fun; //任务处理函数 void* data; //任务处理数据 time_t last_time; //加入空闲队列的时间,用于自动销毁};//任务池,所有任务会投递到任务池中,管理线程负责将任务投递给线程池class TaskPool{public: /* pur @ 初始化任务池,启动任务池空闲队列自动销毁线程 * para @ maxSize 最大任务数,大于0 */ TaskPool(const int & poolMaxSize); ~TaskPool(); /* pur @ 添加任务到任务队列的尾部 * para @ task, 具体任务 * return @ 0 添加成功,负数 添加失败 */ int AddTask(task_fun fun, void* arg); /* pur @ 从任务列表的头获取一个任务 * return @ 如果列表中有任务则返回一个Task指针,否则返回一个NULL */ Task* GetTask(); /* pur @ 保存空闲任务到空闲队列中 * para @ task 已被调用执行的任务 * return @ */ void SaveIdleTask(Task*task); void StopPool();public: void LockIdle(); void UnlockIdle(); void CheckIdleWait(); int RemoveIdleTask(); bool GetStop();private: static void * CheckIdleTask(void *); /* pur @ 获取空闲的task * para @ * para @ * return @ NULL说明没有空闲的,否则从m_idleList中获取一个 */ Task* GetIdleTask(); int GetTaskSize();private: int m_poolSize; //任务池大小 int m_taskListSize; // 统计taskList的大小,因为当List的大小会随着数量的增多而耗时增加 bool m_bStop; //是否停止 std::list<Task*> m_taskList;//所有待处理任务列表 std::list<Task*> m_idleList;//所有空闲任务列表 pthread_mutex_t m_lock; //对任务列表进行加锁,保证每次只能取一个任务 pthread_mutex_t m_idleMutex; //空闲任务队列锁 pthread_cond_t m_idleCond; //空闲队列等待条件 pthread_t m_idleId;;};#endif
threadpool.cpp
/* purpose @ 线程池类,负责线程的创建与销毁,实现线程超时自动退出功能(半驻留) * date @ 2014.01.03 * author @ haibin.wang */#include "threadpool.h"#include <errno.h>#include <string.h>/*#include <iostream>#include <stdio.h>*/Thread::Thread(bool detach, ThreadPool * pool) : m_pool(pool){ pthread_attr_init(&m_attr); if(detach) { pthread_attr_setdetachstate(&m_attr, PTHREAD_CREATE_DETACHED ); // 让线程独立运行 } else { pthread_attr_setdetachstate(&m_attr, PTHREAD_CREATE_JOINABLE ); } pthread_mutex_init(&m_mutex, NULL); //初始化互斥量 pthread_cond_init(&m_cond, NULL); //初始化条件变量 task.fun = 0; task.data = NULL;}Thread::~Thread(){ pthread_cond_destroy(&m_cond); pthread_mutex_destroy(&m_mutex); pthread_attr_destroy(&m_attr);} ThreadPool::ThreadPool() : m_poolMax(0) , m_idleNum(0) , m_totalNum(0) , m_bStop(false){ pthread_mutex_init(&m_mutex, NULL); pthread_mutex_init(&m_runMutex,NULL); pthread_mutex_init(&m_terminalMutex, NULL); pthread_cond_init(&m_terminalCond, NULL); pthread_cond_init(&m_emptyCond, NULL);}ThreadPool::~ThreadPool(){ /*if(!m_threads.empty()) { std::list<Thread*>::iterator it = m_threads.begin(); for(; it != m_threads.end(); ++it) { if(*it != NULL) { pthread_cond_destroy( &((*it)->m_cond) ); pthread_mutex_destroy( &((*it)->m_mutex) ); delete *it; *it = NULL; } } m_threads.clear(); }*/ pthread_mutex_destroy(&m_runMutex); pthread_mutex_destroy(&m_terminalMutex); pthread_mutex_destroy(&m_mutex); pthread_cond_destroy(&m_terminalCond); pthread_cond_destroy(&m_emptyCond);}int ThreadPool::InitPool(const int & poolMax, const int & poolPre){ if(poolMax < poolPre || poolPre < 0 || poolMax <= 0) { return -1; } m_poolMax = poolMax; int iRet = 0; for(int i=0; i<poolPre; ++i) { Thread * thread = CreateThread(); if(NULL == thread) { iRet = -2; } } if(iRet < 0) { std::list<Thread*>::iterator it = m_threads.begin(); for(; it!= m_threads.end(); ++it) { if(NULL != (*it) ) { delete *it; *it = NULL; } } m_threads.clear(); m_totalNum = 0; } return iRet;}void ThreadPool::GetThreadRun(task_fun fun, void* arg){ //从线程池中获取一个线程 pthread_mutex_lock( &m_mutex); if(m_threads.empty()) { pthread_cond_wait(&m_emptyCond,&m_mutex); //阻塞等待有空闲线程 } Thread * thread = m_threads.front(); m_threads.pop_front(); pthread_mutex_unlock( &m_mutex); pthread_mutex_lock( &thread->m_mutex ); thread->task.fun = fun; thread->task.data = arg; pthread_cond_signal(&thread->m_cond); //触发线程WapperFun循环执行 pthread_mutex_unlock( &thread->m_mutex );}int ThreadPool::Run(task_fun fun, void * arg) { pthread_mutex_lock(&m_runMutex); //保证每次只能由一个线程执行 int iRet = 0; if(m_totalNum <m_poolMax) // { if(m_threads.empty() && (NULL == CreateThread()) ) { iRet = -1;//can not create new thread! } else { GetThreadRun(fun, arg); } } else { GetThreadRun(fun, arg); } pthread_mutex_unlock(&m_runMutex); return iRet;}void ThreadPool::StopPool(bool bStop){ m_bStop = bStop; if(bStop) { //启动监控所有空闲线程是否退出的线程 Thread thread(false, this); pthread_create(&thread.m_threadId,&thread.m_attr, ThreadPool::TerminalCheck , &thread); //启动监控所有线程退出线程 //阻塞等待所有空闲线程退出 pthread_join(thread.m_threadId, NULL); } /*if(bStop) { pthread_mutex_lock(&m_terminalMutex); //启动监控所有空闲线程是否退出的线程 Thread thread(true, this); pthread_create(&thread.m_threadId,&thread.m_attr, ThreadPool::TerminalCheck , &thread); //启动监控所有线程退出线程 //阻塞等待所有空闲线程退出 pthread_cond_wait(&m_terminalCond, & m_terminalMutex); pthread_mutex_unlock(&m_terminalMutex); }*/}bool ThreadPool::GetStop(){ return m_bStop;}Thread * ThreadPool::CreateThread(){ Thread * thread = NULL; thread = new Thread(true, this); if(NULL != thread) { int iret = pthread_create(&thread->m_threadId,&thread->m_attr, ThreadPool::WapperFun , thread); //通过WapperFun将线程加入到空闲队列中 if(0 != iret) { delete thread; thread = NULL; } } return thread;}void * ThreadPool::WapperFun(void*arg){ Thread * thread = (Thread*)arg; if(NULL == thread || NULL == thread->m_pool) { return NULL; } ThreadPool * pool = thread->m_pool; pool->IncreaseTotalNum(); struct timespec abstime; memset(&abstime, 0, sizeof(abstime)); while(1) { if(0 != thread->task.fun) { thread->task.fun(thread->task.data); } if( true == pool->GetStop() ) { break; //确定当前任务执行完毕后再判定是否退出线程 } pthread_mutex_lock( &thread->m_mutex ); pool->SaveIdleThread(thread); //将线程加入到空闲队列中 abstime.tv_sec = time(0) + THREAD_WAIT_TIME_OUT; abstime.tv_nsec = 0; if(ETIMEDOUT == pthread_cond_timedwait( &thread->m_cond, &thread->m_mutex, &abstime )) //等待线程被唤醒 或超时自动退出 { pthread_mutex_unlock( &thread->m_mutex ); break; } pthread_mutex_unlock( &thread->m_mutex ); } pool->LockMutex(); pool->DecreaseTotalNum(); if(thread != NULL) { pool->RemoveThread(thread); delete thread; thread = NULL; } pool->UnlockMutex(); return 0;}void ThreadPool::SaveIdleThread(Thread * thread ){ if(thread) { thread->task.fun = 0; thread->task.data = NULL; LockMutex(); if(m_threads.empty()) { pthread_cond_broadcast(&m_emptyCond); //发送不空的信号,告诉run函数线程队列已经不空了 } m_threads.push_front(thread); UnlockMutex(); }}int ThreadPool::TotalThreads(){ return m_totalNum;}void ThreadPool::SendSignal(){ LockMutex(); std::list<Thread*>::iterator it = m_threads.begin(); for(; it!= m_threads.end(); ++it) { pthread_mutex_lock( &(*it)->m_mutex ); pthread_cond_signal(&((*it)->m_cond)); pthread_mutex_unlock( &(*it)->m_mutex ); } UnlockMutex();}void * ThreadPool::TerminalCheck(void* arg){ Thread * thread = (Thread*)arg; if(NULL == thread || NULL == thread->m_pool) { return NULL; } ThreadPool * pool = thread->m_pool; while((false == pool->GetStop()) || pool->TotalThreads() >0 ) { pool->SendSignal(); usleep(IDLE_CHECK_POLL_EMPTY); } //pool->TerminalCondSignal(); return 0;}void ThreadPool::TerminalCondSignal(){ pthread_cond_signal(&m_terminalCond);}void ThreadPool::RemoveThread(Thread* thread){ m_threads.remove(thread);}void ThreadPool::LockMutex(){ pthread_mutex_lock( &m_mutex);}void ThreadPool::UnlockMutex(){ pthread_mutex_unlock( &m_mutex );}void ThreadPool::IncreaseTotalNum(){ LockMutex(); m_totalNum++; UnlockMutex();}void ThreadPool::DecreaseTotalNum(){ m_totalNum--;}
threadpool.h
#ifndef THREADPOOL_H#define THREADPOOL_H/* purpose @ 线程池类,负责线程的创建与销毁,实现线程超时自动退出功能(半驻留)a * 当线程池退出时创建TerminalCheck线程,负责监测线程池所有线程退出 * date @ 2013.12.23 * author @ haibin.wang */#include <list>#include <string>#include "taskpool.h"//通过threadmanager来控制任务调度进程//threadpool的TerminalCheck线程负责监测线程池所有线程退出class ThreadPool;class Thread{public: Thread(bool detach, ThreadPool * pool); ~Thread(); pthread_t m_threadId; //线程id pthread_mutex_t m_mutex; //互斥锁 pthread_cond_t m_cond; //条件变量 pthread_attr_t m_attr; //线程属性 Task task; // ThreadPool * m_pool; //所属线程池};//线程池,负责创建线程处理任务,处理完毕后会将线程加入到空闲队列中,从任务池中class ThreadPool{public: ThreadPool(); ~ThreadPool(); /* pur @ 初始化线程池 * para @ poolMax 线程池最大线程数 * para @ poolPre 预创建线程数 * return @ 0:成功 * -1: parameter error, must poolMax > poolPre >=0 * -2: 创建线程失败 */ int InitPool(const int & poolMax, const int & poolPre); /* pur @ 执行一个任务 * para @ task 任务指针 * return @ 0任务分配成功,负值 任务分配失败,-1,创建新线程失败 */ int Run(task_fun fun, void* arg); /* pur @ 设置是否停止线程池工作 * para @ bStop true停止,false不停止 */ void StopPool(bool bStop);public: //此公有函数主要用于静态函数调用 /* pur @ 获取进程池的启停状态 * return @ */ bool GetStop(); void SaveIdleThread(Thread * thread ); void LockMutex(); void UnlockMutex(); void DecreaseTotalNum(); void IncreaseTotalNum(); void RemoveThread(Thread* thread); void TerminalCondSignal(); int TotalThreads(); void SendSignal();private: /* pur @ 创建线程 * return @ 非空 成功,NULL失败, */ Thread * CreateThread(); /* pur @ 从线程池中获取一个一个线程运行任务 * para @ fun 函数指针 * para @ arg 函数参数 * return @ */ void GetThreadRun(task_fun fun, void* arg); static void * WapperFun(void*); static void * TerminalCheck(void*);//循环监测是否所有线程终止线程private: int m_poolMax;//线程池最大线程数 int m_idleNum; //空闲线程数 int m_totalNum; //当前线程总数 小于最大线程数 bool m_bStop; //是否停止线程池 pthread_mutex_t m_mutex; //线程列表锁 pthread_mutex_t m_runMutex; //run函数锁 pthread_mutex_t m_terminalMutex; //终止所有线程互斥量 pthread_cond_t m_terminalCond; //终止所有线程条件变量 pthread_cond_t m_emptyCond; //空闲线程不空条件变量 std::list<Thread*> m_threads; // 线程列表};#endif
threadpoolmanager.cpp
#include "threadpoolmanager.h"#include "threadpool.h"#include "taskpool.h"#include <errno.h>#include <string.h>/*#include <string.h>#include <sys/time.h>#include <stdio.h>*/ // struct timeval time_beg, time_end;ThreadPoolManager::ThreadPoolManager() : m_threadPool(NULL) , m_taskPool(NULL) , m_bStop(false){ pthread_mutex_init(&m_mutex_task,NULL); pthread_cond_init(&m_cond_task, NULL); /* memset(&time_beg, 0, sizeof(struct timeval)); memset(&time_end, 0, sizeof(struct timeval)); gettimeofday(&time_beg, NULL);*/}ThreadPoolManager::~ThreadPoolManager(){ StopAll(); if(NULL != m_threadPool) { delete m_threadPool; m_threadPool = NULL; } if(NULL != m_taskPool) { delete m_taskPool; m_taskPool = NULL; } pthread_cond_destroy( &m_cond_task); pthread_mutex_destroy( &m_mutex_task ); /*gettimeofday(&time_end, NULL); long total = (time_end.tv_sec - time_beg.tv_sec)*1000000 + (time_end.tv_usec - time_beg.tv_usec); printf("manager total time = %d\n", total); gettimeofday(&time_beg, NULL);*/}int ThreadPoolManager::Init( const int &tastPoolSize, const int &threadPoolMax, const int &threadPoolPre){ m_threadPool = new ThreadPool(); if(NULL == m_threadPool) { return -1; } m_taskPool = new TaskPool(tastPoolSize); if(NULL == m_taskPool) { return -2; } if(0>m_threadPool->InitPool(threadPoolMax, threadPoolPre)) { return -3; } //启动线程池 //启动任务池 //启动任务获取线程,从任务池中不断拿任务到线程池中 pthread_attr_t attr; pthread_attr_init( &attr ); pthread_attr_setdetachstate( &attr, PTHREAD_CREATE_JOINABLE ); pthread_create(&m_taskThreadId, &attr, TaskThread, this); //创建获取任务进程 pthread_attr_destroy(&attr); return 0;}void ThreadPoolManager::StopAll(){ m_bStop = true; LockTask(); pthread_cond_signal(&m_cond_task); UnlockTask(); pthread_join(m_taskThreadId, NULL); //等待当前所有任务执行完毕 m_taskPool->StopPool(); m_threadPool->StopPool(true); // 停止线程池工作}void ThreadPoolManager::LockTask(){ pthread_mutex_lock(&m_mutex_task);}void ThreadPoolManager::UnlockTask(){ pthread_mutex_unlock(&m_mutex_task);}void* ThreadPoolManager::TaskThread(void* arg){ ThreadPoolManager * manager = (ThreadPoolManager*)arg; while(1) { manager->LockTask(); //防止任务没有执行完毕发送了停止信号 while(1) //将任务队列中的任务执行完再退出 { Task * task = manager->GetTaskPool()->GetTask(); if(NULL == task) { break; } else { manager->GetThreadPool()->Run(task->fun, task->data); manager->GetTaskPool()->SaveIdleTask(task); } } if(manager->GetStop()) { manager->UnlockTask(); break; } manager->TaskCondWait(); //等待有任务的时候执行 manager->UnlockTask(); } return 0;}ThreadPool * ThreadPoolManager::GetThreadPool(){ return m_threadPool;}TaskPool * ThreadPoolManager::GetTaskPool(){ return m_taskPool;}int ThreadPoolManager::Run(task_fun fun,void* arg){ if(0 == fun) { return 0; } if(!m_bStop) { int iRet = m_taskPool->AddTask(fun, arg); if(iRet == 0 && (0 == pthread_mutex_trylock(&m_mutex_task)) ) { pthread_cond_signal(&m_cond_task); UnlockTask(); } return iRet; } else { return -3; }}bool ThreadPoolManager::GetStop(){ return m_bStop;}void ThreadPoolManager::TaskCondWait(){ struct timespec to; memset(&to, 0, sizeof to); to.tv_sec = time(0) + 60; to.tv_nsec = 0; pthread_cond_timedwait( &m_cond_task, &m_mutex_task, &to); //60秒超时}
threadpoolmanager.h
#ifndef THREADPOOLMANAGER_H#define THREADPOOLMANAGER_H/* purpose @ * 基本流程: * 管理线程池和任务池,先将任务加入任务池,然后由TaskThread负责从任务池中将任务取出放入到线程池中 * 基本功能: * 1、工作线程可以在业务不忙的时候自动退出部分长时间不使用的线程 * 2、任务池可以在业务不忙的时候自动释放长时间不使用的资源(可通过commondef.h修改) * 3、当程序退时不再向任务池中添加任务,当任务池中所有任务执行完毕后才退出相关程序(做到程序的安全退出) * 线程资源: * 如果不预分配任何处理线程的话,ThreadPool只有当有任务的时候才实际创建需要的线程,最大线程创建数为用户指定 * 当manager销毁的时候,manager会创建一个监控所有任务执行完毕的监控线程,只有当所有任务执行完毕后manager才销毁 * 线程最大数为:1个TaskPool线程 + 1个manager任务调度线程 + ThreadPool最大线程数 + 1个manager退出监控线程 + 1线程池所有线程退出监控线程 * 线程最小数为:1个TaskPool创建空闲任务资源销毁监控线程 + 1个manager创建任务调度线程 * 使用方法: * ThreadPoolManager manager; * manager.Init(100000, 50, 5);//初始化一个任务池为10000,线程池最大线程数50,预创建5个线程的管理器 * manager.run(fun, data); //添加执行任务到manager中,fun为函数指针,data为fun需要传入的参数,data可以为NULL * * date @ 2013.12.23 * author @ haibin.wang * * 详细参数控制可以修改commondef.h中的相关变量值 */#include <pthread.h>typedef void (*task_fun)(void *);class ThreadPool;class TaskPool;class ThreadPoolManager{public: ThreadPoolManager(); ~ThreadPoolManager(); /* pur @ 初始化线程池与任务池,threadPoolMax > threadPoolPre > threadPoolMin >= 0 * para @ tastPoolSize 任务池大小 * para @ threadPoolMax 线程池最大线程数 * para @ threadPoolPre 预创建线程数 * return @ 0:初始化成功,负数 初始化失败 * -1:创建线程池失败 * -2:创建任务池失败 * -3:线程池初始化失败 */ int Init(const int &tastPoolSize, const int &threadPoolMax, const int &threadPoolPre); /* pur @ 执行一个任务 * para @ fun 需要执行的函数指针 * para @ arg fun需要的参数,默认为NULL * return @ 0 任务分配成功,负数 任务分配失败 * -1:任务池满 * -2:任务池new失败 * -3:manager已经发送停止信号,不再接收新任务 */ int Run(task_fun fun,void* arg=NULL);public: //以下public函数主要用于静态函数调用 bool GetStop(); void TaskCondWait(); TaskPool * GetTaskPool(); ThreadPool * GetThreadPool(); void LockTask(); void UnlockTask(); void LockFull();private: static void * TaskThread(void*); //任务处理线程 void StopAll();private: ThreadPool *m_threadPool; //线程池 TaskPool * m_taskPool; //任务池 bool m_bStop; // 是否终止管理器 pthread_t m_taskThreadId; // TaskThread线程id pthread_mutex_t m_mutex_task; pthread_cond_t m_cond_task;};#endif
main.cpp
#include <iostream>#include <string>#include "threadpoolmanager.h"#include <sys/time.h>#include <string.h>#include <stdlib.h>#include <pthread.h>using namespace std;int seq = 0;int billNum =0;int inter = 1;pthread_mutex_t m_mutex;void myFunc(void*arg){ pthread_mutex_lock(&m_mutex); seq++; if(seq%inter == 0 ) { cout << "fun 1=" << seq << endl; } if(seq>=1000000000) { cout << "billion" << endl; seq = 0; billNum++; } pthread_mutex_unlock(&m_mutex); //sleep();}int main(int argc, char** argv){ if(argc != 6) { cout << "必须有5个参数 任务执行次数 任务池大小 线程池大小 预创建线程数 输出间隔" << endl; cout << "eg: ./test 999999 10000 100 10 20" << endl; cout << "上例代表创建一个间隔20个任务输出,任务池大小为10000,线程池大小为100,预创建10个线程,执行任务次数为:999999" << endl; return 0; } double loopSize = atof(argv[1]); int taskSize = atoi(argv[2]); int threadPoolSize = atoi(argv[3]); int preSize = atoi(argv[4]); inter = atoi(argv[5]); pthread_mutex_init(&m_mutex,NULL); ThreadPoolManager manager; if(0>manager.Init(taskSize, threadPoolSize, preSize)) { cout << "初始化失败" << endl; return 0; } cout << "*******************初始化完成*********************" << endl; struct timeval time_beg, time_end; memset(&time_beg, 0, sizeof(struct timeval)); memset(&time_end, 0, sizeof(struct timeval)); gettimeofday(&time_beg, NULL); double i=0; for(; i<loopSize; ++i) { while(0>manager.Run(myFunc,NULL)) { usleep(100); } } gettimeofday(&time_end, NULL); long total = (time_end.tv_sec - time_beg.tv_sec)*1000000 + (time_end.tv_usec - time_beg.tv_usec); cout << "total time =" << total << endl; cout << "total num =" << i << " billion num=" << billNum<< endl; cout << __FILE__ << "将关闭所有线程" << endl; //pthread_mutex_destroy(&m_mutex); return 0;}
Windows核心编程 第11章 线程池的使用
11.1 方案1:异步调用函数 QueueUserWorkItem
11.2 方案2:按规定的时间间隔调用函数 CreateTimerQueueTimer
11.3 方案3:当单个内核对象变为已通知状态时调用函数 RegisterWaitForSingleObject
11.4 方案4:当异步I / O请求完成运行时调用函数 BindIoCompletionCallback
- 线程与线程池
- 线程池 线程优先级
- Executor线程,线程池
- 线程、多线程、线程池
- IOS-线程、线程池
- Java线程:线程池
- 线程和线程池
- 线程、多线程、线程池
- 线程、多线程、线程池
- 线程(六)线程池
- ExecutorService(线程池)+线程
- 线程和线程池
- 线程&线程池 简略
- 线程和线程池
- 线程池 线程锁
- 线程、线程池总结
- 线程与线程池
- 线程、锁、线程池
- 杭电1042(N!)
- 如何搭建简易蓝牙定位系统
- 虚拟机性能监控与故障处理工具-JDK命令行工具
- centos7下搭建lamp
- iOS边城之推送APNS详解
- 线程池
- WebBrowser自动点击弹出提示框alert、弹出对话框confirm、屏蔽弹出框、屏蔽弹出脚本错误的解决办法
- 求两个日期之间相隔的天数:
- IMPDP的一个坑
- Hive:用Java代码通过JDBC连接Hiveserver
- HttpServletResponse response(中文乱码、文件下载、定时刷新、控制缓存、重定向、注意事项)
- 学习网页设计与制作之跑马灯标记
- CXF客户端请求服务流程
- Linux tcpdump命令详解