linux---线程池种类以及实现(固定数量)

线程池是什么
一堆固定的数量的或者有最大数量限制的线程+任务队列->用于我们并发处理请求,避免了大量频繁的线程的创建和销毁的事件成本,同时避免了峰值压力带来瞬间大量线程被创建资源耗尽,程序奔溃的危险。

线程池的参数

  • 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 }  

猜你喜欢

转载自blog.csdn.net/boke_fengwei/article/details/90375524
今日推荐