C++线程池的实现(二)
参考文章:http://blog.csdn.net/huyiyang2010/archive/2010/08/10/5801597.aspx
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
1 // CThread.h 2 3 #ifndef __MY_THREAD_H__ 4 #define __MY_THREAD_H__ 5 6 #include <windows.h> 7 #include <process.h> 8 9 // 线程执行接口 10 class CRunnable 11 { 12 public: 13 CRunnable(){} 14 virtual ~CRunnable() {} 15 virtual void Run() = 0; 16 }; 17 18 class CThread : public CRunnable 19 { 20 enum 21 { 22 enmMaxThreadNameLen = 64, 23 }; 24 private: 25 explicit CThread(const CThread & rhs); 26 public: 27 CThread(); 28 CThread(CRunnable * pRunnable); 29 30 ~CThread(void); 31 bool Start(); 32 virtual void Run(); 33 void Join(int timeout = -1); 34 void Resume(); 35 void Suspend(); 36 bool Terminate(unsigned long ExitCode); 37 void dump(); 38 unsigned int GetThreadID(); 39 friend bool operator==(const CThread& left,const CThread& right); 40 private: 41 static unsigned int WINAPI StaticThreadFunc(void * arg); 42 void init(); 43 private: 44 HANDLE m_hHandle; 45 CRunnable * const m_pRunnable; 46 unsigned int m_nThreadID; 47 volatile bool m_bRun; 48 }; 49 50 #endif
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
1 #include "CThread.h" 2 #include <iostream> 3 using namespace std; 4 5 CThread::CThread(void):m_pRunnable(NULL) 6 { 7 init(); 8 } 9 10 CThread::CThread(CRunnable * pRunnable):m_pRunnable(pRunnable) 11 { 12 init(); 13 } 14 15 CThread::~CThread(void) 16 { 17 if(m_pRunnable != NULL ) 18 { 19 delete m_pRunnable; 20 } 21 } 22 23 void CThread::init() 24 { 25 m_bRun = false; 26 m_hHandle = (HANDLE)_beginthreadex(NULL, 0, StaticThreadFunc, this, CREATE_SUSPENDED, &m_nThreadID); 27 } 28 29 30 bool CThread::Start() 31 { 32 Resume(); 33 return (NULL != m_pRunnable); 34 } 35 36 void CThread::Run() 37 { 38 if(NULL != m_pRunnable) 39 { 40 m_pRunnable->Run(); 41 if(m_pRunnable != NULL) 42 { 43 delete m_pRunnable; 44 } 45 } 46 } 47 48 void CThread::Join(int timeout) 49 { 50 if(NULL == m_hHandle || m_bRun == false ) 51 { 52 return; 53 } 54 if(timeout <= 0) 55 { 56 timeout = INFINITE; 57 } 58 ::WaitForSingleObject(m_hHandle, timeout); 59 } 60 61 void CThread::Resume() 62 { 63 if( NULL == m_hHandle || m_bRun == true ) 64 { 65 return; 66 } 67 m_bRun = true; 68 ::ResumeThread(m_hHandle); 69 } 70 71 void CThread::Suspend() 72 { 73 if(NULL == m_hHandle || m_bRun == false ) 74 { 75 return; 76 } 77 ::SuspendThread(m_hHandle); 78 } 79 80 bool CThread::Terminate(unsigned long ExitCode) 81 { 82 if(NULL == m_hHandle || m_bRun == false ) 83 { 84 return true; 85 } 86 if(::TerminateThread(m_hHandle, ExitCode)) 87 { 88 ::CloseHandle(m_hHandle); 89 return true; 90 } 91 return false; 92 } 93 94 unsigned int CThread::GetThreadID() 95 { 96 return m_nThreadID; 97 } 98 99 unsigned int CThread::StaticThreadFunc(void * arg) 100 { 101 CThread * pThread = (CThread *)arg; 102 pThread->Run(); 103 pThread->m_bRun = false; 104 return 0; 105 } 106 107 void CThread::dump() 108 { 109 cout<<"run="<<m_bRun<<",id="<<m_nThreadID<<endl; 110 } 111 bool operator==(const CThread& left,const CThread& right) 112 { 113 return left.m_nThreadID == right.m_nThreadID; 114 }
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
1 #ifndef _STATIC_QUEUE_H_ 2 #define _STATIC_QUEUE_H_ 3 4 // 静态queue模板,用数组实现的队列,在初始化的时候需要指定长度 5 template<class T> 6 class Static_Queue{ 7 public: 8 Static_Queue(); 9 virtual ~Static_Queue(); 10 bool init(const unsigned int size); 11 bool push(T t); 12 bool pop(T & t); 13 unsigned int GetElementCnt(); 14 void dump(); 15 private: 16 volatile unsigned int m_nSize; 17 T *m_arrT; 18 volatile unsigned int m_nHead; 19 volatile unsigned int m_nTail; 20 volatile unsigned int m_nEmptyCnt; 21 }; 22 23 24 template<class T> 25 Static_Queue<T>::Static_Queue() 26 { 27 m_nSize = 0; 28 m_arrT = NULL; 29 m_nEmptyCnt = 0; 30 m_nHead = 0; 31 m_nTail = 0; 32 } 33 34 template<class T> 35 Static_Queue<T>::~Static_Queue() 36 { 37 delete[] m_arrT; 38 m_arrT = NULL; 39 } 40 41 template<class T> 42 bool Static_Queue<T>::init(const unsigned int size) 43 { 44 m_nSize = size; 45 m_arrT = new T[m_nSize]; 46 if(m_arrT == NULL) 47 { 48 return false; 49 } 50 memset(m_arrT,0,sizeof(T)*m_nSize); 51 m_nEmptyCnt = m_nSize; 52 return true; 53 } 54 55 template<class T> 56 bool Static_Queue<T>::push(T t) 57 { 58 if( m_nEmptyCnt <= 0 ) 59 { 60 return false; 61 } 62 m_arrT[m_nTail++] = t; 63 if(m_nTail >= m_nSize) 64 { 65 m_nTail = 0; 66 } 67 m_nEmptyCnt--; 68 return true; 69 } 70 71 template<class T> 72 bool Static_Queue<T>::pop(T & t) 73 { 74 if( m_nEmptyCnt >= m_nSize ) 75 { 76 return false; 77 } 78 t = m_arrT[m_nHead++]; 79 if( m_nHead >= m_nSize ) 80 { 81 m_nHead = 0; 82 } 83 m_nEmptyCnt++; 84 return true; 85 } 86 87 template<class T> 88 unsigned int Static_Queue<T>::GetElementCnt() 89 { 90 return m_nSize - m_nEmptyCnt; 91 } 92 93 template<class T> 94 void Static_Queue<T>::dump() 95 { 96 cout<<"head= "<<m_nHead<<" "<<"tail= "<<m_nTail<<endl; 97 cout<<"["; 98 for(int i = 0;i < m_nSize;i++ ) 99 { 100 cout<<m_arrT[i]<<" "; 101 } 102 cout<<"]"<<endl; 103 } 104 105 106 #endif
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
1 #ifndef _MY_HASH_INT_H_ 2 #define _MY_HASH_INT_H_ 3 4 template<class T,class K> 5 class HashInt{ 6 public: 7 HashInt(); 8 virtual ~HashInt(); 9 private: 10 typedef struct tagElement 11 { 12 T data; 13 K key; 14 bool use; 15 tagElement(){use = false;} 16 ~tagElement(){} 17 }Element; 18 volatile unsigned int m_nSize; 19 Element *m_arrT; 20 volatile unsigned int m_nElementCnt; 21 // 查找 22 bool find(K key,unsigned int &index); 23 public: 24 // 初始化,分配内存 25 bool init(const unsigned int size); 26 // 哈希函数 27 unsigned int hash(K key); 28 // ELF哈希函数 29 unsigned int hash_elf(char *str); 30 // 插入 31 bool insert(T data,K key); 32 // 删除 33 bool remove(K key); 34 // 查找 35 bool find(K key,T &data); 36 // 修改 37 bool modify(T data,K key); 38 // 元素个数 39 unsigned int get_element_cnt(); 40 // 下标索引 41 bool get_by_index(unsigned int index,T &data); 42 void dump(); 43 }; 44 45 template<class T,class K> 46 bool HashInt<T, K>::get_by_index( unsigned int index,T &data ) 47 { 48 if( m_nElementCnt == 0) 49 { 50 return false; 51 } 52 if(m_arrT[index].use == false) 53 { 54 return false; 55 } 56 data = m_arrT[index].data; 57 return true; 58 } 59 60 template<class T,class K> 61 unsigned int HashInt<T, K>::get_element_cnt() 62 { 63 return m_nElementCnt; 64 } 65 66 template<class T,class K> 67 unsigned int HashInt<T, K>::hash_elf( char *str) 68 { 69 unsigned int locate = 0; 70 unsigned int x = 0; 71 while (*str) 72 { 73 locate = (locate << 4) + (*str++);//hash左移4位,当前字符ASCII存入hash低四位。 74 if ((x = locate & 0xF0000000L) != 0) 75 {//如果最高的四位不为0,则说明字符多余7个,如果不处理,再加第九个字符时,第一个字符会被移出,因此要有如下处理。 76 locate ^= (x >> 24); 77 //清空28-31位。 78 locate &= ~x; 79 } 80 } 81 return locate%m_nSize; 82 } 83 84 template<class T,class K> 85 HashInt<T, K>::~HashInt() 86 { 87 if(m_arrT != NULL) 88 { 89 delete[] m_arrT; 90 } 91 } 92 93 template<class T,class K> 94 HashInt<T, K>::HashInt() 95 { 96 m_arrT = NULL; 97 m_nSize = 0; 98 m_nElementCnt = 0; 99 } 100 101 template<class T,class K> 102 void HashInt<T, K>::dump() 103 { 104 cout<<"m_nElementCnt="<<m_nElementCnt<<",m_nSize="<<m_nSize<<endl; 105 for(unsigned int i = 0;i < m_nSize;i++) 106 { 107 if(m_arrT[i].use == true) 108 { 109 cout<<i<<"-"; 110 cout<<"["<<m_arrT[i].key<<"="<<m_arrT[i].data<<"] "; 111 } 112 } 113 cout<<endl; 114 } 115 116 template<class T,class K> 117 bool HashInt<T, K>::modify( T data,K key ) 118 { 119 if( m_nElementCnt == 0) 120 { 121 return false; 122 } 123 bool exist = false; 124 unsigned int index; 125 exist = find(key,index); 126 if( exist == true ) 127 { 128 m_arrT[index].data = data; 129 } 130 return false; 131 } 132 133 template<class T,class K> 134 bool HashInt<T, K>::find( K key,T &data ) 135 { 136 if( m_nElementCnt == 0) 137 { 138 return false; 139 } 140 bool exist = false; 141 unsigned int index; 142 exist = find(key,index); 143 if( exist == true ) 144 { 145 data = m_arrT[index].data; 146 return true; 147 } 148 return false; 149 } 150 151 152 template<class T,class K> 153 bool HashInt<T, K>::find( K key,unsigned int &index ) 154 { 155 if( m_nElementCnt == 0) 156 { 157 return false; 158 } 159 unsigned int locate = hash(key),i = 1; 160 while(i < m_nSize) 161 { 162 if( m_arrT[locate].use == true && m_arrT[locate].key == key) 163 { 164 index = locate; 165 return true; 166 } 167 locate = (locate + i)%m_nSize; 168 i++; 169 } 170 return false; 171 } 172 173 174 template<class T,class K> 175 bool HashInt<T, K>::remove( K key ) 176 { 177 // 表为空 178 if( m_nElementCnt == 0 ) 179 { 180 return false; 181 } 182 bool exist = false; 183 unsigned int index; 184 exist = find(key,index); 185 if( exist == true ) 186 { 187 m_arrT[index].use = false; 188 m_nElementCnt--; 189 return true; 190 } 191 return false; 192 } 193 194 template<class T,class K> 195 bool HashInt<T, K>::insert( T data,K key) 196 { 197 // 表已满 198 if( m_nElementCnt == m_nSize ) 199 { 200 return false; 201 } 202 unsigned int locate = hash(key),i = 1; 203 while(i < m_nSize) 204 { 205 if( m_arrT[locate].use == false) 206 { 207 m_arrT[locate].data = data; 208 m_arrT[locate].key = key; 209 m_arrT[locate].use = true; 210 m_nElementCnt++; 211 return true; 212 } 213 locate = (locate + i)%m_nSize; 214 i++; 215 } 216 return false; 217 } 218 219 template<class T,class K> 220 unsigned int HashInt<T, K>::hash( K key ) 221 { 222 return key%m_nSize; 223 } 224 225 template<class T,class K> 226 bool HashInt<T, K>::init( const unsigned int size ) 227 { 228 m_nSize = size; 229 m_arrT = new Element[m_nSize]; 230 m_nElementCnt = 0; 231 //cout<<"size = "<<sizeof(Element)*m_nSize<<endl; 232 return true; 233 } 234 235 #endif
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
1 #ifndef __MY_MY_THREAD_POOL_H_ 2 #define __MY_MY_THREAD_POOL_H_ 3 4 #include "CThread.h" 5 #include <windows.h> 6 #include "StaticQueue.h" 7 #include "HashInt.h" 8 9 using namespace std; 10 11 class CMyThreadPool 12 { 13 public: 14 CMyThreadPool(void); 15 virtual ~CMyThreadPool(void); 16 // 初始化线程池,创建minThreads个线程 17 bool Initialize(unsigned int minThreadCnt,unsigned int maxThreadCnt,unsigned int maxTaskQueueLength); 18 bool AddTask( CRunnable *pRunnable, bool bRun = true); 19 void Terminate(); 20 // 获取线程数量 21 unsigned int GetThreadCnt(); 22 private: 23 // 从任务队列头中取出一个任务 24 CRunnable *GetTask(); 25 // 执行任务线程 26 static unsigned int WINAPI StaticThreadFunc(void * arg); 27 private: 28 // 工作者类 29 class CWorker : public CThread 30 { 31 public: 32 CWorker(CMyThreadPool *pThreadPool,CRunnable *pFirstTask = NULL); 33 ~CWorker(); 34 void Run(); 35 private: 36 CMyThreadPool * const m_pThreadPool; 37 CRunnable * m_pFirstTask; 38 volatile bool m_bRun; 39 }; 40 41 typedef HashInt<CWorker*,unsigned int> ThreadPool; 42 typedef Static_Queue<CRunnable *> Tasks; 43 44 CRITICAL_SECTION m_csTasksLock; 45 CRITICAL_SECTION m_csThreadPoolLock; 46 47 // 线程池 48 ThreadPool m_ThreadPool; 49 // 垃圾线程 50 ThreadPool m_TrashThread; 51 // 任务队列 52 Tasks m_Tasks; 53 // 是否在运行 54 volatile bool m_bRun; 55 // 能否插入任务 56 volatile bool m_bEnableInsertTask; 57 // 最小线程数 58 volatile unsigned int m_minThreads; 59 // 最大线程数 60 volatile unsigned int m_maxThreads; 61 // 最大挂起任务数量 62 volatile unsigned int m_maxPendingTasks; 63 }; 64 65 #endif
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
1 #include "CMyThreadPool.h" 2 #include <iostream> 3 #include <time.h> 4 5 using namespace std; 6 7 CMyThreadPool::CWorker::CWorker(CMyThreadPool *pThreadPool,CRunnable *pFirstTask) 8 :m_pThreadPool(pThreadPool),m_pFirstTask(pFirstTask),m_bRun(true) 9 { 10 11 } 12 13 CMyThreadPool::CWorker::~CWorker() 14 { 15 16 } 17 18 void CMyThreadPool::CWorker::Run() 19 { 20 CRunnable * pTask = NULL; 21 while(m_bRun) 22 { 23 // 取出一个任务 24 if(NULL == m_pFirstTask) 25 { 26 pTask = m_pThreadPool->GetTask(); 27 } 28 else 29 { 30 pTask = m_pFirstTask; 31 m_pFirstTask = NULL; 32 } 33 // 如果没有取到任务 34 if(NULL == pTask) 35 { 36 EnterCriticalSection(&(m_pThreadPool->m_csThreadPoolLock)); 37 // 如果运转的线程数大于最小线程数,需要清除多余的线程 38 if(m_pThreadPool->GetThreadCnt() > m_pThreadPool->m_minThreads) 39 { 40 CWorker *p = NULL; 41 unsigned int thread_id = this->GetThreadID(); 42 if(m_pThreadPool->m_ThreadPool.find(thread_id,p) == true) 43 { 44 if(p == NULL) 45 { 46 cout<<"find failed,p == NULL,thread_id = "<<thread_id<<endl; 47 continue; 48 } 49 m_pThreadPool->m_ThreadPool.remove(thread_id); 50 m_pThreadPool->m_TrashThread.insert(p,thread_id); 51 } 52 else 53 { 54 cout<<"find by thread_id failed,thread_id = "<<thread_id<<endl; 55 } 56 m_bRun = false; 57 } 58 else 59 { 60 // 等待已经开始运行的线程结束 61 for(unsigned int i = 0;i < m_pThreadPool->m_TrashThread.get_element_cnt();i++) 62 { 63 CWorker *p = NULL; 64 if(m_pThreadPool->m_TrashThread.get_by_index(i,p) == true) 65 { 66 if(p == NULL) 67 { 68 cout<<"get_by_index failed,p == NULL"<<endl; 69 continue; 70 } 71 p->Join(); 72 m_pThreadPool->m_TrashThread.remove(p->GetThreadID()); 73 delete p; 74 } 75 } 76 } 77 LeaveCriticalSection(&(m_pThreadPool->m_csThreadPoolLock)); 78 continue; 79 } 80 else 81 { 82 pTask->Run(); 83 delete pTask; 84 pTask = NULL; 85 } 86 } 87 } 88 89 90 CMyThreadPool::CMyThreadPool(void):m_bRun(false),m_bEnableInsertTask(false) 91 { 92 InitializeCriticalSection(&m_csTasksLock); 93 InitializeCriticalSection(&m_csThreadPoolLock); 94 } 95 96 CMyThreadPool::~CMyThreadPool(void) 97 { 98 DeleteCriticalSection(&m_csTasksLock); 99 DeleteCriticalSection(&m_csThreadPoolLock); 100 } 101 102 bool CMyThreadPool::Initialize(unsigned int minThreadCnt,unsigned int maxThreadCnt,unsigned int maxTaskQueueLength) 103 { 104 if(minThreadCnt == 0) 105 { 106 return false; 107 } 108 if(minThreadCnt > maxThreadCnt) 109 { 110 return false; 111 } 112 if(m_ThreadPool.init(maxThreadCnt) == false 113 || m_TrashThread.init(maxThreadCnt) == false 114 || m_Tasks.init(maxTaskQueueLength) == false) 115 { 116 return false; 117 } 118 m_minThreads = minThreadCnt; 119 m_maxThreads = maxThreadCnt; 120 m_maxPendingTasks = maxTaskQueueLength; 121 unsigned int i = m_ThreadPool.get_element_cnt(); 122 for(; i<minThreadCnt; i++) 123 { 124 //创建线程 minThreadCnt 个线程 125 CWorker * pWorker = new CWorker(this); 126 if(NULL == pWorker) 127 { 128 return false; 129 } 130 EnterCriticalSection(&m_csThreadPoolLock); 131 if(m_ThreadPool.insert(pWorker,pWorker->GetThreadID()) == false) 132 { 133 return false; 134 } 135 LeaveCriticalSection(&m_csThreadPoolLock); 136 pWorker->Start(); 137 } 138 // 可以开始插入任务队列 139 m_bRun = true; 140 m_bEnableInsertTask = true; 141 return true; 142 } 143 144 unsigned int CMyThreadPool::GetThreadCnt() 145 { 146 return m_ThreadPool.get_element_cnt(); 147 } 148 149 CRunnable * CMyThreadPool::GetTask() 150 { 151 CRunnable *Task = NULL; 152 EnterCriticalSection(&m_csTasksLock); 153 if( m_Tasks.GetElementCnt() != 0 ) 154 { 155 m_Tasks.pop(Task); 156 } 157 LeaveCriticalSection(&m_csTasksLock); 158 return Task; 159 } 160 161 bool CMyThreadPool::AddTask( CRunnable *pRunnable, bool bRun /*= true*/ ) 162 { 163 if(m_bEnableInsertTask == false) 164 { 165 return false; 166 } 167 if(NULL == pRunnable) 168 { 169 return false; 170 } 171 // 如果达到最大挂起任务数量 172 if(m_Tasks.GetElementCnt() >= m_maxPendingTasks) 173 { 174 // 如果小于最大线程数 175 if(m_ThreadPool.get_element_cnt() < m_maxThreads) 176 { 177 CWorker * pWorker = new CWorker(this, pRunnable); 178 if(NULL == pWorker) 179 { 180 cout<<"error:CWorker * pWorker = new CWorker(this, pRunnable)"<<endl; 181 return false; 182 } 183 EnterCriticalSection(&m_csThreadPoolLock); 184 if(m_ThreadPool.insert(pWorker,pWorker->GetThreadID()) == false) 185 { 186 cout<<"error:m_ThreadPool.insert(pWorker,pWorker->GetThreadID(),id"<<pWorker->GetThreadID()<<endl; 187 return false; 188 } 189 LeaveCriticalSection(&m_csThreadPoolLock); 190 pWorker->Start(); 191 } 192 else 193 { 194 return false; 195 } 196 } 197 else 198 { 199 EnterCriticalSection(&m_csTasksLock); 200 if( m_Tasks.push(pRunnable) == false ) 201 { 202 cout<<"error:m_Tasks.push(pRunnable) == false"<<endl; 203 return false; 204 } 205 LeaveCriticalSection(&m_csTasksLock); 206 } 207 //m_ThreadPool.dump(); 208 return true; 209 } 210 211 void CMyThreadPool::Terminate() 212 { 213 m_bEnableInsertTask = false; 214 while(m_Tasks.GetElementCnt() > 0) 215 { 216 Sleep(1); 217 } 218 m_bRun = false; 219 m_minThreads = 0; 220 m_maxThreads = 0; 221 m_maxPendingTasks = 0; 222 while(m_ThreadPool.get_element_cnt() > 0) 223 { 224 Sleep(1); 225 } 226 EnterCriticalSection(&m_csThreadPoolLock); 227 for(unsigned int i = 0;i < m_TrashThread.get_element_cnt();i++) 228 { 229 CWorker *p = NULL; 230 if(m_TrashThread.get_by_index(i,p) == true) 231 { 232 if(p == NULL) 233 { 234 cout<<"get_by_index failed,p == NULL"<<endl; 235 return; 236 } 237 p->Join(); 238 m_TrashThread.remove(p->GetThreadID()); 239 } 240 } 241 LeaveCriticalSection(&m_csThreadPoolLock); 242 }
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
1 #include <iostream> 2 #include <time.h> 3 #include <iomanip> 4 #include "CThread.h" 5 #include "CThreadPool.h" 6 #include "CMyThreadPool.h" 7 8 using namespace std; 9 10 class R : public CRunnable 11 { 12 public: 13 R(int t):m_nt(t) 14 { 15 } 16 ~R() 17 { 18 cout<<"~R:"<<m_nt<<endl; 19 } 20 void Run() 21 { 22 Sleep(m_nt); 23 cout<<"i am "<<m_nt<<endl; 24 } 25 friend ostream &operator<<(ostream &out,const R &r) 26 { 27 out<<r.m_nt; 28 return out; 29 } 30 friend bool operator < (const R &l,const R &r) 31 { 32 return l < r; 33 } 34 void display() 35 { 36 cout<<m_nt<<" "; 37 } 38 int m_nt; 39 }; 40 41 42 int main() 43 { 44 R *r1 = new R(200); 45 CMyThreadPool *myThreadPool = new CMyThreadPool(); 46 if(myThreadPool->Initialize(1,100,100) == false) 47 { 48 cout<<"inti failed!"<<endl; 49 return 1; 50 } 51 for (int i = 0;i < 20;i++) 52 { 53 R *r = new R(20 -i); 54 if(myThreadPool->AddTask(r) == false) 55 { 56 cout<<"add task failed"<<endl; 57 } 58 } 59 myThreadPool->Terminate(); 60 delete myThreadPool; 61 system("pause"); 62 return 0; 63 }