Linux——线程池概念以及实现

线程池

1.概念:

顾名思义就是许多线程的一个集合。

2.线程池的意义:

虽然线程是轻量级的进程,创建的开销比进程小,但是,频繁的创建与销毁线程也会得不偿失,导致线程的创建与销毁所占的时间成本远大于任务处理的时间成本;因此我们将线程创建后不再销毁而是先放在一起,任务一旦分配就直接进行处理,任务执行完毕,统一销毁。这样就大大提高了任务处理的效率。

3.特点:

(1)线程池中的线程全是消费者线程

(2)线程池中的线程数目是由上限的--为并避免出现峰值压力,导致资源瞬间被耗尽

4.实现:

5.代码实现:

//实现一个线程池:
#include <iostream>
#include <stdlib.h>
#include <thread>
#include <queue>
#include <vector>
#include <pthread.h>
#include <unistd.h>
#include <sstream>
#include <time.h>

using std::endl;
#define MAX_THREAD 5    //最大线程数量5
#define MAX_QUEUE 10    //最大结点数量10

typedef void(*handler_t)(int);

class MyTask{
  private:                                       
    int _data;            //任务的数据类型--整型    
    handler_t _handler;  //数据的处理方式--函数指针 
  public:                                           
    MyTask(int data,handler_t handler):             
      _data(data),                                  
      _handler(handler){}                           
    //任务布置                                      
    void SetTask(int data,handler_t handler){
      _data = data;
      _handler = handler;
      return;                                                                              
    }               
    //任务处理的函数
    void Run(){   
      return _handler(_data);
    }
};              
                                       
                                        
class ThreadPool{
  private:                    
    std::queue<MyTask> _queue;           //任务队列
    int _capacity;                       //队列所能容纳的最大结点数量  
    pthread_mutex_t _mutex;              //互斥锁
    pthread_cond_t _cond_pro;            //条件变量--生产者
    pthread_cond_t _cond_con;            //条件变量--消费者
    int _thr_max;                        //线程池内最大线程数量 
    bool _quit_flag;                     //标志位--标记是否还有线程
    int _thr_cur;                        //记录当前的线程数量--防止单词唤醒有遗漏的线程
    std::vector<std::thread> _thr_list;  //管理线程的列表
  private:                                                           
    void thr_start(){                        
      //出队拿数据--再处理数据
      while(1){          
        pthread_mutex_lock(&_mutex);                                                   
        while(_queue.empty()){
          //队空,并且没有任务--退出
          if(_quit_flag == true){
            //在任意线程退出的情况下都要进行解锁
            std::cout << "thread exit" << pthread_self() << endl;
            pthread_mutex_unlock(&_mutex);
            _thr_cur--;                
            return;                     
            //pthread_exit(NULL);
          }                   
          pthread_cond_wait(&_cond_con,&_mutex);   
        }                                                              
        //有数据                                 
        MyTask tt = _queue.front();                        
        _queue.pop();                                      
        pthread_mutex_unlock(&_mutex);                          
        pthread_cond_signal(&_cond_pro);                           
        //任务处理要放在解锁之后,否则会造成同一时间只有一个线程在处理任务;           
        //必须是可重入函数                               
        tt.Run();                                                    
      }                                      
      return;                 
    }                    
  public:                                                                      
    //构造函数:初始化所有成员变量
    ThreadPool(int maxq = MAX_QUEUE, int maxt = MAX_THREAD):
      _capacity(maxq),           
      _thr_max(maxt),                           
      _thr_list(maxt),                                           
      _quit_flag(false){                  
        pthread_mutex_init(&_mutex,NULL);
        pthread_cond_init(&_cond_pro,NULL);
        pthread_cond_init(&_cond_con,NULL);
      }                       
                                                   
    //对所有线程进行初始化                                             
    bool PoolInit(){                             
      _thr_cur = 0;                                        
      for(int i = 0; i < _thr_max; ++i){                   
        _thr_list[i] = std::thread(&ThreadPool::thr_start,this);
        _thr_cur++;                                                
        //直接分离线程,处理完毕直接退出,资源自动释放,不必再等待             
        _thr_list[i].detach();                           
      }                                                              
    //添加任务--本质上就是入队操作
    bool AddTask(MyTask& tt){
      //入队
      pthread_mutex_lock(&_mutex);
      while(_queue.size() == _capacity){
        //入队--生产者入队,
        pthread_cond_wait(&_cond_pro,&_mutex);
        
      }
      _queue.push(tt);
      pthread_mutex_unlock(&_mutex);
      pthread_cond_signal(&_cond_con);
      return true;
    }


    bool PoolStop(){
      pthread_mutex_lock(&_mutex);
      _quit_flag = true;
      //为防止改成真的时候,有些线程已经陷入了休眠,
      //则不会再去thr_start()里边去判断标志位是否为真,则线程不会退出     
      //故需要唤醒线程
      //为防止线程唤醒之时在处理任务,唤醒之后现入阻塞
      //则需要判断当前线程数量,如果还有线程就广播唤醒
      while(_thr_cur > 0){
        pthread_cond_broadcast(&_cond_con);
         usleep(1000);
       }                           
       return true;                      
     }                                                         
                                               
     //析构函数:销毁所变量、生产者与消费者的条件变量
     ~ThreadPool(){
       pthread_mutex_destroy(&_mutex);
       pthread_cond_destroy(&_cond_pro);
       pthread_cond_destroy(&_cond_con);
     }             
 };   
 
 void test(int data){
   srand(time(NULL));
   int nsec = rand() % 5;          
   std::stringstream ss; 
   ss << "thread" << pthread_self() << "processing data";
   ss << data << "and sleep" << nsec << "sec\n";
                       
   //ss.str()获取字符串                                
   std::cout << ss.str();                              
   sleep(nsec);            
   return;                                  
}

int main(){
  ThreadPool pool;
  pool.PoolInit();
  for(int i = 0; i < 10; ++i){
    MyTask tt(i, test);
    pool.AddTask(tt);
  }

  pool.PoolStop();
  return 0;
}                                 
发布了58 篇原创文章 · 获赞 43 · 访问量 4398

猜你喜欢

转载自blog.csdn.net/Wz_still_shuai/article/details/100664602