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

Linux——线程池

发布时间:2022-10-11 18:30:21 所属栏目:Linux 来源:网络
导读: 目录
一.概念

线程池:见名知义,就是多个线程构成的集合。其中线程的个数是确定的,并不是固定的。
为什么要有线程池?
如果每次都只创建一个线程,首先当用户请求过多时,每次都需要创建

目录

一.概念

线程池linux_linux c 线程池_linux epoll 线程池

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

为什么要有线程池?

如果每次都只创建一个线程,首先当用户请求过多时,每次都需要创建一个线程,创建线程需要时间和调度开销,这样会影响缓存的局部性和整体的性能。其次线程池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;
}

(编辑:成都站长网)

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