一、什么是线程池
线程池=一个或多个线程+任务队列
线程池是一种线程使用模式。线程过多会带来调度开销,进而影响缓存局部性和整体性能。而线程池维护着多个线程,等待
着监督管理者分配可并发执行的任务。这避免了在处理短时间任务时创建与销毁线程的代价。线程池不仅能够保证内核的充分利
用,还能防止过分调度。可用线程数量应该取决于可用的并发处理器、处理器内核、内存、网络sockets等的数量。
二、线程池的作用
1、防止过度消耗资源
2、.避免大量线程频繁创建销毁的成本
三、线程池使用场景
1. 需要大量的线程来完成任务,且完成任务的时间比较短。 WEB服务器完成网页请求这样的任务,使用线程池技术是非常合适
的。因为单个任务小,而任务数量巨大,可以想象一个热门网站的点击次数。 但对于长时间的任务请求,线程池的优点就不明
显了。因为请求时间比线程的创建时间大多了。
2. 对性能要求苛刻的应用,比如要求服务器迅速响应客户请求。
3. 接受突发性的大量请求,但不至于使服务器因此产生大量线程的应用。突发性大量客户请求,在没有线程池情况下,将产生大
量线程,虽然理论上大部分操作系统线程数目最大值不是问题,短时间内产生大量线程可能使内存到达极限,出现错误。.
四、 如何创建一个线程池
1.思路:
创建一个任务类:包含一个任务处理函数
创建一个线程池:1. 创建固定数量线程池,循环从任务队列中获取任务对象。
2. 获取到任务对象后,执行任务对象中的任务接口。//创建线程
//创建线程安全的任务队列
//提供任务入队出队接口,线程池初始化销毁接口
2.实例:
完成功能:线程实现两数相加
main.cc:
#include"thread_pool.hpp"
#define NUM 5
int add(int x,int y)
{
return x+y;
}
int main()
{
ThreadPool *tp=new ThreadPool(NUM);
tp->InitThreadPool();
int count=1;
while(1)
{
Task t(count,count-1,add);//创建任务
tp->AddTask(t);//任务处理
count++;
}
return 0;
}
thread_pool.hpp:
1 #ifndef __THREAD_POOL_HPP__
2 #define __THREAD_POOL_HPP__
3
4 #include<iostream>
5 #include<queue>
6 #include<pthread.h>
7 #include<unistd.h>
8
9 using namespace std;
10
11 typedef int (*cal_t)(int,int);
12 class Task{
13 private:
14 int x;
15 int y;
16 cal_t handler_task;//执行函数
17 int z;
18 public:
19 Task(int x_,int y_,cal_t handler_task_)
20 :x(x_),y(y_),handler_task(handler_task_)
21 {}
22 void Run()
23 {
24 z=handler_task(x,y);
25 }
26 void Show()
27 {
28 //for test
29 cout<<"thread"<<pthread_self()<<"Handler Task don e."<<"Result is:"<<z<<endl;
30 sleep(1);
31 }
32 ~Task()
33 {}
34 };
35
36 class ThreadPool{
37 private:
38 int thread_nums;//线程个数
39 std::queue<Task> t_queue;//任务队列
40 pthread_mutex_t lock;
41 pthread_cond_t cond;
42 bool is_stop;//设置停止
43 private:
44 static void *thread_routine(void *arg)
45 {
46 ThreadPool *tp=(ThreadPool*)arg;
47 pthread_detach(pthread_self());
48 for(;;){
49 tp->LockQueue();
50 while(tp->IsEmpty()){//没有任务时等待
51 tp->IdleThread();
52 }
53 Task t=tp->GetTask();//获取任务
54 tp->UnlockQueue();//
55
56 t.Run();//处理任务
57 t.Show();
58 }
59 }
60
61 void NotifyOneThread()
62 {
63 pthread_cond_signal(&cond);
64 }
65
66 void NotifyAllThreads()
67 {
68 pthread_cond_broadcast(&cond);
69 }
70 public:
71 ThreadPool(int num_)
72 :thread_nums(num_)
73 {}
74
75 void InitThreadPool()
76 {
77 pthread_mutex_init(&lock,NULL);
78 pthread_cond_init(&cond,NULL);
79 int i=0;
80 for(;i<thread_nums;++i)
81 {
82 pthread_t tid;
83 pthread_create(&tid,NULL,thread_routine,( void*)this);
84 }
85 }
86
87 void LockQueue()
88 {
89 pthread_mutex_lock(&lock);
90 }
91
92 void UnlockQueue()
93 {
94 pthread_mutex_unlock(&lock);
95 }
96
97 bool IsEmpty()
98 {
99 return t_queue.size()==0?true:false;
100 }
101
102 void IdleThread()
103 {
104 if(is_stop){
105 UnlockQueue();
106 thread_nums--;
107 pthread_exit((void *)0);
108 cout<<"pthread"<<pthread_self()<<"quit"<<endl ;
109 return;
110 }
111 pthread_cond_wait(&cond,&lock);
112 }
113
114 void AddTask(Task &t)
115 {
116 LockQueue();
117 if(is_stop){
118 UnlockQueue();
119 return;
120 }
121 t_queue.push(t);
122 NotifyOneThread();
123 UnlockQueue();
124 }
125
126 Task GetTask()
127 {
128 Task t=t_queue.front();
129 t_queue.pop();
130 return t;
131 }
132
133 void Stop()
134 {
135 LockQueue();
136 is_stop=true;
137 UnlockQueue();
138 while(thread_nums>0){
139 NotifyAllThreads();
140 }
141 }
142
143 ~ThreadPool()
144 {
145 pthread_mutex_destroy(&lock);
146 pthread_cond_destroy(&cond);
147 }
148 };
149
150 #endif
结果: