加入收藏 | 设为首页 | 会员中心 | 我要投稿 拼字网 - 核心网 (https://www.hexinwang.cn/)- 科技、建站、经验、云计算、5G、大数据,站长网!
当前位置: 首页 > 服务器 > 搭建环境 > Linux > 正文

Linux——线程 池

发布时间:2022-11-21 12:49:39 所属栏目:Linux 来源:
导读:  目录

  一.概念

  线程池:见名知义,就是多个线程构成的集合。其中线程的个数是确定的,并不是固定的。

  为什么要有线程池?

  如果每次都只创建一个线程,首先当用户请求过多时,每次
  目录
 
  一.概念
 
  线程池:见名知义,就是多个线程构成的集合。其中线程的个数是确定的,并不是固定的。
 
  为什么要有线程池?
 
  如果每次都只创建一个线程,首先当用户请求过多时,每次都需要创建一个线程,创建线程需要时间和调度开销,这样会影响缓存的局部性和整体的性能。其次线程池linux,如果无上限一直创建线程,还会导致CPU的过分调度。
 
  线程池已经创建好了一定数量的线程,等待着分配任务,这样避免了处理任务时的线程创建和销毁。线程池里线程个数确定,能够保证内核的充分利用,还能防止过分调度。
 
  线程池中可用线程数量取决于可用额并发处理器,处理器内核,内存,网络socket等的数量。
 
  线程池的应用场景:
 
  需要大量的线程来完成任务,且完成人物的时间比较短。比如:WEB服务器完成网页请求这样的任务,因为当个任务小,并且任务量巨大,你可以想象一个热门网站的请求次数。但是对于长时间的任务,线程池的优先就不明显了。比如:一个Telnet连接请求,因为Telnet会话时间比线程创建时间大多了。对性能要求苛刻的应用,比如要求服务器迅速响应客户请求。接收突发性的大量请求,但是不至于使服务器因此产生大量线程应用。突发性大量客户请求,在没有线程池的情况下,将产生大量线程,虽然理论上大部分操作系统线程数目最大值不是问题,短时间内产生大量的线程可能使内存到达极限,出现错误。二.线程池实现
 
  线程池实际也是一个生产者消费者模型,接收任务,往任务队列中放任务的是生产者,从任务队列中拿任务并执行的是消费者。
 
  主线程是生产者,用来接收任务和放任务。
 
  int main(){
    mythreadpool *tp=new mythreadpool();
    tp->threadinit();
    int count=10;
    while(1){
      //sleep(1);
      int x=rand()+1;
      int y=rand()%20+1;
      Task t(x,y);
      //put里有加锁,不需要加锁了
      tp->Put(t);
      std::cout<<"put Task done..."<ThreadQuit();
    delete tp;
    return 0;
  }
  线程池中的线程的创建封装在类中,线程获得任务的函数就会成为类的成员函数,在C++中,类的成员函数会隐含一个this指针,导致函数有两个参数,但是只能由一个参数,所以要对线程获得任务的函数加一个static,并且需要将调用对象的this指针作为参数传进来,不然就不能调用其它成员函数。
 
      //成员函数,由this指针作为参数,
      //线程函数,只能有一个参数,所以要加static
      static void *handler(void *arg){
        mythreadpool *p_this = (mythreadpool *)arg;
        while(1){
          p_this->ThreadLock();
   //不退出,没有数据要等待
          while(!(p_this->_quit)&&(p_this->IsEmpty())){
            p_this->ThreadWait();
          }
   //退出没有数据,直接退出
   //退出有数据,还需要执行任务
          if(p_this->_quit&&p_this->IsEmpty()){
            p_this->ThreadUnlock();
            p_this->ThreadExit();
          }
   //执行任务
          Task t;
          p_this->Get(t);
          p_this->ThreadUnlock();
          int res=0;
          res = t.Add();
          std::cout<
  注意如果服务还在运行,线程不退出,生产者不能有等待的情况,如果生产者等待,用户链接不上了。
 
  线程退出:
 
  设置一个标志位quit,起始设置false,不退出。当需要退出时将quit设置为true。
 
  此时可能会有线程在等待,需要全部唤醒线程。
 
  当线程还没有完全退出时,需要生产者等待。
 
  当还有任务时,需要线程继续执行任务,执行完任务后才能退出。
 
  总代码:
 
  #pragma once
  #include
  #include
  #include
  #include
  #define NUM 5
  struct Task{
    Task(){};
    Task(int x, int y){
      _x=x;
      _y=y;
    }
    ~Task(){};
    int _x;
    int _y;
    int Add(){
      return _x + _y;
    }
  };
  class mythreadpool{
    private:
      void ThreadLock(){
        pthread_mutex_lock(&_lock);
      }
      void ThreadUnlock(){
        pthread_mutex_unlock(&_lock);
      }
      void ThreadWait(){
        pthread_cond_wait(&_cond, &_lock);
      }
      void ProductorWait(){
        pthread_cond_wait(&_pcond, &_lock);
      }
      void ProductorSignal(){
        pthread_cond_signal(&_pcond);
      }
      void ThreadSignal(){
        pthread_cond_signal(&_cond);
      }
   //唤醒全部线程
      void ThreadSignalAll(){
        pthread_cond_broadcast(&_cond);
      }
      bool IsEmpty(){
        return _q.empty();
      }
   //退出线程
      void ThreadExit(){
        _numthread--;
        printf("%lu is exit\n",pthread_self());
        ProductorSignal();
        pthread_exit(0);
      }
    public:
      mythreadpool(size_t num = NUM)
      :_numthread(num)
       ,_quit(false)
      {}
      //成员函数,由this指针作为参数,
      //线程函数,只能有一个参数,所以要加static
      static void *handler(void *arg){
        mythreadpool *p_this = (mythreadpool *)arg;
        while(1){
          p_this->ThreadLock();
   //不退出,没有数据要等待
          while(!(p_this->_quit)&&(p_this->IsEmpty())){
            p_this->ThreadWait();
          }
   //退出没有数据,直接退出
   //退出有数据,还需要执行任务
          if(p_this->_quit&&p_this->IsEmpty()){
            p_this->ThreadUnlock();
            p_this->ThreadExit();
          }
   //执行任务
          Task t;
          p_this->Get(t);
          p_this->ThreadUnlock();
          int res=0;
          res = t.Add();
          std::cout< _q;//任务队列
      size_t _numthread;//线程个数
      pthread_mutex_t _lock;//锁
      pthread_cond_t _cond;//消费者在此等待
      pthread_cond_t _pcond;//生产者在此等待
      
      bool _quit;//是否退出
  };
  #include"mythreadpool.hpp"
  int main(){
    mythreadpool *tp=new mythreadpool();
    tp->threadinit();
    int count=10;
    while(1){
      //sleep(1);
      int x=rand()+1;
      int y=rand()%20+1;
      Task t(x,y);
      //put里有加锁,不需要加锁了
      tp->Put(t);
      std::cout<<"put Task done..."<ThreadQuit();
    delete tp;
    return 0;
  }
 

(编辑:拼字网 - 核心网)

【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容!