线程池是什么
一堆固定的数量的或者有最大数量限制的线程+任务队列->用于我们并发处理请求,避免了大量频繁的线程的创建和销毁的事件成本,同时避免了峰值压力带来瞬间大量线程被创建资源耗尽,程序奔溃的危险。
线程池的参数
- corepollsize:核心池的大小,默认情况下,在创建线程池后,每当有新的任务
- maximumpoolsize:线程池中最多可以创建的线程数
- keeplivetime:线程空闲状态时,最多保持多久的时间会终止,默认情况下,当线程池中的线程数大于corepollsize时才会起作用,直到线程数不大于corepollsize.
- workQueue:阻塞队列,用来存储等待的任务
- rejectedExceutionHandler:任务拒绝处理器,这个包含了四种:abortpolicy丢弃任务,抛出异常,discardopolicy拒绝执行,不抛出异常,discardoldestpolicy丢弃任务缓存队列中最老的任务,classerRunsPOlicy线程池不执行这个任务,主线程自己执行
线程池的种类(以及简单使用场景)
- newFisedThreadPool(定长线程池)
一个有制定的线程数的线程池,有核心的超线程,里面有固定的线程数量,响应的速度快,正规的并发线程,多用于服务器,固定的线程数有系统资源设置,核心线程是没有超时机制,队列大小没有限制。除非线程池关闭了核心线程才会被回收 - newCachedThreadPool (可缓冲线程池)
只有非核心线程,最大线程数很大,每新来一个任务,当没有空余线程的时候就会重新创建一个线程,这里面含有超时机制,当空与的线程超过s内没有用到的话,就会别回收,他可以一定程度上减少频繁创建、销毁线程的系统开销,适用于时间短并且数量多的任务场景 - ScheduledThreadPool(周期线程池)
创建一个定长线程池,支持定时以及周期性任务执行,通过schedule方法可以设置任务的周期执行 - newSingleThreadExector(但任务线程池)
创建一个单线程化的线程池,它只会用唯一的工作线程来执行任务,保证所有的任务按照指定书序(FIFO,LIFO,优先级)执行,每次任务到来后都会进行阻塞队列,然后按指定书序执行。
实现简单线程数量固定的线程池:
1 #include <iostream>
2 #include <queue>
3 #include <pthread.h>
4 #include <time.h>
5 #include <stdlib.h>
6 #include <unistd.h>
7 using std::cout;
8 using std::endl;
9 //任务类
10 typedef bool (*task_callback)(int data);
11 bool deal_data(int data){
12 srand(time(NULL));
13 unsigned int n = rand()%5+1;
14 cout<<"线程id"<<pthread_self()<<
15 "处理数据"<<data<<"处理数据了,并且睡了"<<n<<"s"<<endl;
16 sleep(n);
17 return true;
18 }
19 class Task{
20 public:
21 Task(){
22 }
23 ~Task(){
24 }
25 void Settask(int data,task_callback handle){
26 _data = data;
27 _handle = handle;
28 }
29 bool run(){
30 return _handle(_data);
31 }
32
33 private:
34 int _data;//需要处理的数据
35 task_callback _handle;
36 };
37 //线程池类
38 class PthreadPool{
39 public:
40 bool ThreadInit(){
41 //对我们的数据进行初始化操作
42 _max_size = 10;
43 _cur_size = 10;
44 _quit_flag = false;
45 _capacity = 10;
46 pthread_mutex_init(&_mutex,NULL);
47 pthread_cond_init(&_pro_con,NULL);
48 pthread_cond_init(&_con_con,NULL);
49 //生产我们的线程
50 int i ;
51 pthread_t tid;
52 int ret = 0;
53 for(i = 0;i < _max_size;i++){
54 ret = pthread_create(&tid,NULL,thr_start,(void*)this);
55 if(ret != 0){
56 return false;
57 }
58 pthread_detach(tid);//加入到我们的线程分离,就不用管释放了
59 }
60 return true;
61 }
62 bool PushTask(Task& task){
63 if(_quit_flag == true){
64 return false;
65 }
66 //加锁
67 Queue_Lock();
68 //添加任务,在条件变量不为0的情况下
69 while(QueueIsfull()){//队列满了就等待
70 ProWait();
71 }
72 _queue.push(task);
73 ConWakeUp();//唤醒我们的消费者
74 Queue_Unlock();//解锁的操作
75 return true;
76 }
77 bool ThreadQuit(){
78 if(_quit_flag != true){
79 _quit_flag = true;
80 }
81 //此时进行唤醒所有的线程进行删除
82 while(_cur_size > 0){
83 ConWakeAll();
84 sleep(1);
85 }
86 return true;
87 }
88 private:
89 static void* thr_start(void* arg){
90 PthreadPool* pool = (PthreadPool*)arg;
91 while(1){
92 //判断队列是不是空,时空就ConWait();
93 pool->Queue_Lock();
94 while(pool->QueueIsEmpty()){
95 pool->Con_wait();
96 }
97 Task task;//添加任务到
98 pool->PopTask(&task);
99 pool->ProWakeUp();
100 pool->Queue_Unlock();//解锁
101 task.run();
102 }
103 return NULL;
104 }
105 bool QueueIsEmpty(){
106 return _queue.empty();
107 }
108 bool PopTask(Task* task){
109 *task = _queue.front();
110 _queue.pop();
111 return true;
112 }
113 void ProWakeUp(){//生产者进行唤醒
114 pthread_cond_signal(&_pro_con);
115 }
116 bool QueueIsfull(){//判断队列是不是满了
117 return _capacity == _queue.size();
118 }
119 bool Queue_Lock(){//进行加锁的操作
120 return pthread_mutex_lock(&_mutex);
121 }
122 bool Queue_Unlock(){//进行解锁的操作
123 return pthread_mutex_unlock(&_mutex);
124 }
125 void ProWait(){//生产者进行等待
126 pthread_cond_wait(&_pro_con,&_mutex);
127 }
128 void Con_wait(){//消费者进行等待
129 if(_quit_flag == true){
130 pthread_mutex_unlock(&_mutex);
131 cout<<"thread:"<<pthread_self()<<"已经退出了"<<endl;
132 _cur_size--;
133 pthread_exit(NULL);
134 }
135 pthread_cond_wait(&_con_con,&_mutex);
136 }
137 void ConWakeUp(){//唤醒我们的消费者
138 pthread_cond_signal(&_con_con);
139 }
140 void ConWakeAll(){//唤醒我们所有的
141 cout<<"wake up all" <<endl;
142 pthread_cond_broadcast(&_con_con);
143 }
144 private:
145 int _max_size;//线程池中的最大的数量
146 int _cur_size;//线程当前的
147 bool _quit_flag;//线程退出的标志
148 int _capacity;//队列中的最大节点数目
149 std::queue<Task> _queue;//任务队列
150 pthread_mutex_t _mutex;//锁
151 pthread_cond_t _pro_con;//生产者的条件变量
152 pthread_cond_t _con_con;//消费者的条件变量
153 };
154
155 int main(){
156 PthreadPool pool;
157 pool.ThreadInit();//初始化
158 //添加我们的任务
159 Task task[10];//是个任务
160 int i = 0;
161 for(i = 0;i<10;i++){
162 task[i].Settask(i,deal_data);
163 pool.PushTask(task[i]);
164 }
165 pool.ThreadQuit();
166 return 0;
167 }