1 线程池原理
线程池的原理很简单,就是预先建立些空闲线程,并把它们投入睡眠中。当有任务到达时,就唤醒一个线程来处理,处理完后放回线程池中。因为线程池对空闲线程的维护,所以避免了对线程创建的开销,当频繁使用线程且处理工作量很小的情况下,使用线程池可以有效的提升系统性能。
2 线程池实现
线程池的实现主要分为四部分,线程的创建、添加任务到线程池中、子线程取出任务进行处理以及把执行完成的任务写回主线程。
使用线程池的一般是为了防止主线程阻塞,所以把阻塞的任务(如读写磁盘等)交予子线程处理,实现方式一般分为双队列(同时使用互斥锁和条件变量)和管道两种。
使用双队列的是因为在主线程非阻塞模式下,获取互斥锁时只能用try_lock的方式,从而不一定能获取到互斥锁,所以放任务时需要使用两个队列,当获取不到锁时就放入另一个队列,一个队列的任务执行完后,交换两队列;
3 双队列线程池程序实现:
头文件:
18 #ifndef __CTHREAD
19 #define __CTHREAD
20
21 #include<queue>
22 #include<string>
23 #include<pthread.h>
24 #include<iostream>
25 using namespace std;
26
27
28 class CTask
29 {
30 protected:
31 string m_strTaskName;
32 void *m_ptrData;
33 public:
34
35
36 CTask(){}
37
38 CTask(string taskName)
39 {
40 this->m_strTaskName=taskName;
41 m_ptrData=NULL;
42 }
43 virtual int Run()=0;
44 void SetData(void *data); //设置任务数据
45
46 };
47
48
49 class CThreadPool
50 {
51 private:
52 int m_threadNum; //线程数量
53
54 static pthread_mutex_t m_threadMutex;
55 static pthread_mutex_t m_taskMutex;
56 static pthread_cond_t m_threadCond;
57 static pthread_cond_t m_taskCond;
58
59 static queue<CTask*>* taskQueue1; //任务队列1
60 static queue<CTask*>* taskQueue2; //任务队列2
61 static queue<CTask*>* taskback; //任务返回队列
62 public:
63 CThreadPool(int);
64 static int swapqueue(queue<CTask *>* &,queue<CTask*>* &); //交换任务队列1和任务队列2的任务
65 static void* ThreadFunc(void *arg);
66 int Create();
67 int AddTask(CTask*); //加入任务
68 CTask* GetTaskback(); //返回任务
69 int Check();
70 static int clearQueue(queue<CTask*>*);
71 ~CThreadPool();
72
73 };
74
75 #endif
cpp文件:
18 #include"CThread.h"
19 #include<string>
20 #include<iostream>
21 using namespace std;
22
23 void CTask::SetData(void *data)
24 {
25 m_ptrData=data;
26 }
27
28 queue<CTask*>* CThreadPool::taskQueue2=new queue<CTask*>[1];
29 queue<CTask*>* CThreadPool::taskQueue1=new queue<CTask*>[1];
30 queue<CTask*>* CThreadPool::taskback=new queue<CTask*>[1];
31
32 pthread_mutex_t CThreadPool::m_threadMutex=PTHREAD_MUTEX_INITIALIZER;
33 pthread_mutex_t CThreadPool::m_taskMutex=PTHREAD_MUTEX_INITIALIZER;
34 pthread_cond_t CThreadPool::m_threadCond=PTHREAD_COND_INITIALIZER;
35 pthread_cond_t CThreadPool::m_taskCond=PTHREAD_COND_INITIALIZER;
36
37 CThreadPool::CThreadPool(int threadNum)
38 {
39 this->m_threadNum=threadNum;
40 Create();
41 }
42
43 int CThreadPool::swapqueue(queue<CTask*>* &a,queue<CTask*>* &b) //交换两个队列
44 {
45 queue<CTask*>* temp;
46 temp=a;
47 a=b;
48 b=temp; cout<<"swap!!!!!"<<endl;
49 }
50
51 void *CThreadPool::ThreadFunc(void *arg)
52 {
53 pthread_t tid=pthread_self();
54 while(1)
55 {
56 CTask *task;
57 if(taskQueue1->empty()&&!taskQueue2->empty())
58 swapqueue(taskQueue1,taskQueue2);
59
60 pthread_mutex_lock(&m_threadMutex);
61
62 if(taskQueue1->empty())
63 {
64 pthread_cond_wait(&m_threadCond,&m_threadMutex);
65 pthread_mutex_unlock(&m_threadMutex);
66 continue;
67 }
68
69 task=taskQueue1->front();
70 taskQueue1->pop();
71 pthread_mutex_unlock(&m_threadMutex);
72
73 task->Run();
74
75 pthread_mutex_lock(&m_taskMutex);
76 taskback->push(task);
77 //pthread_cond_signal(&m_taskCond);
78 pthread_mutex_unlock(&m_taskMutex);
79
80 }
81 return 0;
82 }
83
84 int CThreadPool::AddTask(CTask *task) //添加任务到线程池中
85 {
86 if(pthread_mutex_trylock(&m_threadMutex)==0)
87 {
88 taskQueue1->push(task);
89 pthread_cond_signal(&m_threadCond);
90 cout<<"add to queue1"<<endl;
91 pthread_mutex_unlock(&m_threadMutex);
92
93 }else
94 {
95 taskQueue2->push(task);
96 pthread_cond_signal(&m_threadCond);
97 cout<<"add to queue2"<<endl;
98 pthread_mutex_unlock(&m_threadMutex);
99 }
100
101 return 0;
102
103 }
104
105 CTask* CThreadPool::GetTaskback() //取出执行完的任务
106 {
107 CTask *task;
108
109 // if(pthread_mutex_trylock(&m_taskMutex)==0)
110
111 if(!taskback->empty())
112 {
113 task=taskback->front();
114 taskback->pop();
115 //pthread_mutex_unlock(&m_taskMutex);
116
117 return task;
118
119 }
120
121 return NULL;
122 }
123
124 int CThreadPool::Create() //创建线程池
125 {
126 pthread_t tid=0;
127 for(int i=0;i<m_threadNum;i++)
128 {
129 if(pthread_create(&tid,NULL,ThreadFunc,NULL)!=0)
130 {
131 cout<<"pthead_create error";
132 return -1;
133 }
134 }
135 return 0;
136 }
137
138 int CThreadPool::clearQueue(queue<CTask*> *a)
139 {
140 while(!a->empty())
141 {
142 a->pop();
143 }
144
145 delete a;
146 return 0;
147 }
148
149 int CThreadPool::Check() //防止有任务为执行
150 {
151 if(!taskQueue1->empty()||!taskQueue2->empty())
152 pthread_cond_signal(&m_threadCond);
153 }
154
155 CThreadPool::~CThreadPool()
156 {
157 clearQueue(taskQueue1);
158 clearQueue(taskQueue2);
159 pthread_cond_destroy(&m_threadCond);
160 }
161
测试文件:
19 #include"CThread.cpp"
20 #include<iostream>
21 #include<sys/time.h>
22
23 using namespace std;
24
25 class CWorkTask:public CTask
26 {
27 public:
28 CWorkTask(){}
29 int Run()
30 {
31 cout<<(char*)this->m_ptrData<<endl;
32 sleep(1);
33 return 0;
34 }
35 };
36
37 int main()
38 {
39 struct timeval begin,end;
40
41 CWorkTask tt;
42 char str[]="!!!!!!!!!!this is a test";
43
44 tt.SetData((void*)str);
45 CThreadPool threadpool(5);
46
47 for(int i=0;i<10;i++)
48 {
49 threadpool.AddTask(&tt);
50
51 }
52
53 while(1) //不让进程退出
54 {
55 sleep(10);
56 threadpool.Check();
57 }
58
59 }
执行结果:
0 0