线程池

本文介绍了线程池的相关知识。线程池是一种线程使用模式,能避免处理短时间任务时创建与销毁线程的代价,保证内核充分利用。阐述了其工作机制,即任务提交给线程池,由其分配给空闲线程。还说明了适用场景,如大量短任务、对性能要求高及应对突发性大量请求的应用。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

线程池

基本概念

一种线程使用模式。线程过多会带来调度开销,进而影响缓存局部性和整体性能。而线程池维护着多个 线程,等待着监督管理者分配可并发执行的任务。这避免了在处理短时间任务时创建与销毁线程的代价。线程池不 仅能够保证内核的充分利用,还能防止过分调度。可用线程数量应该取决于可用的并发处理器、处理器内核、内 存、网络sockets等的数量;

线程池的工作机制:

在线程池的编程模式下,任务是提交给整个线程池,而不是直接提交给某个线程,线程池在拿到任务后,就在内部寻找是否有空闲的线程,如果有,则将任务交给某个空闲的线程。

一个线程同时只能执行一个任务,但可以同时向一个线程池提交多个任务

线程池的应用场景

需要大量的线程来完成任务,且完成任务的时间比较短。

WEB服务器完成网页请求这样的任务,使 用线程池技术是非常合适的。

因为单个任务小,而任务数量巨大,你可以想象一个热门网站的点击次数。

但对于 长时间的任务,比如一个Telnet连接请求,线程池的优点就不明显了。因为Telnet会话时间比线程的创建时间大 多了。

对性能要求苛刻的应用,比如要求服务器迅速响应客户请求。

接受突发性的大量请求,但不至于使服务器因此产生大量线程的应用。

突发性大量客户请求,在没 有线程池情况下,将产生大量线程,虽然理论上大部分操作系统线程数目最大值不是问题,短时间内产生大量线程 可能使内存到达极限,出现错误.

实现一个线程池

在这里插入图片描述

#include <iostream>
#include <queue>
#include <pthread.h>
#include <stdlib.h>
#include <unistd.h>
#include <time.h>
#define MAX_THR 10
#define MAX_QUE 5
typedef bool (*task_callback)(int data);//定义一个函数指针,规定对数据的处理
bool deal_data(int data){
  srand(time(NULL));
  int n = rand() % 5;
  std::cout<<"thread:"<<pthread_self()<<"deal_data"<<data<<"sleep"<<n<<std::endl;
  return true;
}
//执行的任务
class Task{
  public:
    Task(int data = 0):
    _data(data);
    {}
  public:
     void SetTask(int data,task_callback handle){
            _data = data;
            _handle = handle;
    }
    bool Run(){
      return _handle(_data);
    }
  private:
    int _data;
    task_callback _handle;
};
class ThreadPool{
  public:
    ~ThreadPool(){
      pthread_mutex_destroy(&_mutex);
      pthread_cond_destroy(&_cond_con);
      pthread_cond_destroy(&_cond_pro);
    }
    //构造函数没有返回值然而  线程创建不一定成功
    bool ThreadInit(int max_thr = MAX_THR,int max_que = MAX_QUE) {
      _quit_flag = false;
      _max_thr = max_thr;
      _cur_thr = max_thr;
      _capacity = max_que;

      pthread_mutex_init(&_mutex,NULL);
      pthread_cond_init(&_cond_con,NULL);
      pthread_cond_init(&_cond_pro,NULL);

      int ret;
      //创建线程
      pthread_t tid;
      for(int i = 0;i < _max_thr;i++){
        pthread_create(&tid,NULL,thr_start,(void*)this);
        if(ret != 0)
          return false;
        pthread_detach(tid);
      }
      return true;
    }
    bool PushTask(Task& task){
      //当线程要退出时不再插入任务
      if(_quit_flag == true){
        return false;
      }
       QueueLock();
       while(QueueIsFull()){
         ProWait();
       }
       _quene.push(task);
       ConWeakup();
       QueueUnlock();
       return true;
    }
    void TaskPop(Task& task){
      QueueLock();
      while(QueueIsEmpty()){
          ConWait();
        }
        task = _quene.front();
        _quene.pop();
        ProWeakup();
        QueueUnlock();
    }
    void TreadQuit(){
      if(_quit_flag != true){
        _quit_flag = true;
      } 
      while(1){
        //退出之前有可能大量的线程陷入阻塞状态不能退出需要唤醒
        ConWeakupAll();
        sleep(1);
      }
    }
  private:
    bool QueueIsEmpty(){
      return _quene.empty();
    }
    bool QueueIsFull(){
      return _quene.size()==_capacity;
    }
    void QueueLock(){
      pthread_mutex_lock(&_mutex);
    }
    void QueueUnlock(){
      pthread_mutex_unlock(&_mutex);
    }
    void ConWait(){
      if(_quit_flag == true){
        //在线程退出的地方都要解锁
        QueueUnlock();
        std::cout<<"thread:"<<pthread_self()<<"exit"<<std::endl;
       _cur_thr--;
       pthread_exit(NULL);
      }
      pthread_cond_wait(&_cond_con,&_mutex);
    }
    void ConWeakup(){
      pthread_cond_signal(&_cond_con);
    }
    void ConWeakupAll(){
      pthread_cond_broadcast(&_cond_con);
    }
    void ProWait(){
      pthread_cond_wait(&_cond_pro,&_mutex);
    }
    void ProWeakup(){
      pthread_cond_signal(&_cond_pro);
    }
    //这里不能有this指针不满足函数要求所以加static修饰
    static void* thr_start(void* arg){
      ThreadPool* pool = (ThreadPool*)arg;
      while(1){
        pool->QueueLock();
        Task task;
        pool->TaskPop(task);
        pool->QueueUnlock();
        task.Run();
      }
    }
  private:
    int _max_thr;//最大线程数量
    int _cur_thr;//当前线程数量
    int _quit_flag;//退出标志
    int _capacity;//队列的最大数量
    std::queue<Task> _quene;
    pthread_mutex_t _mutex;
    pthread_cond_t _cond_pro;
    pthread_cond_t _cond_con;

};
int main(){
  ThreadPool pool;
  pool.ThreadInit();
  Task task[10];
  for(int i = 0;i < 10; ++i){
    task[i].SetTask(i,deal_data);
    pool.PushTask(task[i]);
  }
  pool.TreadQuit();
  return 0;
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值