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

Linux 通用 线程池的实现

发布时间:2022-12-15 12:49:50 所属栏目:Linux 来源:
导读:  用百度搜索一下“Linux线程池”,很出现很多个结果,有的提供的源程序是可以使用的,但仔细分析后,发现其设计结构的并不太合理。线程池的设计有两个难点。1、在池中线程完成一个任务后自动阻塞,并等
  用百度搜索一下“Linux线程池”,很出现很多个结果,有的提供的源程序是可以使用的,但仔细分析后,发现其设计结构的并不太合理。线程池的设计有两个难点。1、在池中线程完成一个任务后自动阻塞,并等待被唤醒。2、池中的空闲线程数会随着任务的多少而有一个动态的变化,如任务多而空闲线程过少时,程序会创建新的线程来补充;当任务少而空闲线程过多时,程序会取消一些空闲线程以节约系统资源。Linux系统的一个进程最多支持2024个线程。
 
  一些网络服务器在单位时间内需要处理大量的连接请求,但服务的时间去很短。使用普通的方法,即接收一个服务请求,创建一个服务线程方法来提供服务,会浪费系统很多资源。因为线程的创建和销毁己经占用了大量的CPU。而使用线程池方法能够很好的解决这一问题。
 
  线程池采用预创建技术,在应用程序启动后,立即创建一定数量的线程,并让这些线程处于阻塞状态,(即空闲线程)不消耗CPU,只占用较小的内存空间。当任务来临时,应用程序即唤醒一个空闲的线程,并处理此任务。当此线程处理完任务后,重新回到阻塞状态,并不退出。当系统比较空闲时,大部分线程处于空闲状态,线程池会自动销毁一些线程,回收系统资源。
 
  下面一个线程池构架。不同于一些网友对线程池的设计,此构架更为简单。程序是根据一网络上现有程序修改的,链接地址:,有兴趣的话可以自己去看源代码,在这里不做过多介绍。
 
  线程池共有两个类,WorkThread 和 ThreadPool。WorkThread是工作线程类,即线程池中线程所需执行的任务。当有一个新的WorkerThread对象到达时,即有一个处于阻塞状态的线程被唤醒。
 
  class WorkerThread{
 
  public:
 
  intid;
 
  unsigned virtual executeThis()
 
  {
 
  return 0;
 
  }
 
  WorkerThread(int id) : id(id) {}
 
  virtual~WorkerThread(){}
 
  };
 
  ThreadPool类负责对线程池进行管理,包括:创建新线程、线程间的同步、把新的任务加入到工作队列中、让池中的线程数动态的改变。其类声明如下:
 
  class ThreadPool{
 
  public:
 
  ThreadPool();
 
  ThreadPool(int maxThreadsTemp);
 
  virtual~ThreadPool();
 
  void destroyPool(int maxPollSecs);
 
  bool assignWork(WorkerThread *worker);
 
  boolfetchWork(WorkerThread **worker);
 
  void initializeThreads();
 
  static void*threadExecute(void *param);
 
  static pthread_mutex_t mutexSync;
 
  staticpthread_mutex_t mutexWorkCompletion;
 
  protected:
 
  staticvoidMoveToBusyList(pthread_tid);//moveand idle thread to busy thread
 
  staticvoidMoveToIdleList(pthread_t id);
 
  void CreateIdleThread(int num);
 
  voidDeleteIdleThread(int num);
 
  pthread_mutex_tm_VarMutex;//mutex for var
 
  pthread_mutex_tmutexThreadList;
 
  static pthread_mutex_t mutexBusyList;
 
  staticpthread_mutex_t mutexIdleList;
 
  private:
 
  unsigned intm_InitNum;
 
  unsigned int m_MaxNum;
 
  unsigned intm_AvailLow;
 
  unsigned intm_AvailHigh;
 
  //unsignedint m_AvailNum;
 
  sem_tavailableWork;
 
  //sem_tavailableThreads;
 
  vector<pthread_t>m_ThreadList;//ThreadList
 
  staticvector<pthread_t>m_BusyList;//BusyList
 
  staticvector<pthread_t>m_IdleList;//IdleList
 
  vector<WorkerThread *>workerQueue;
 
  //int topIndex;
 
  //intbottomIndex;
 
  intincompleteWork;//number of works be done
 
  intqueueSize;//thesize of workQueue
 
  };
 
  在源程序上进行了适当的修改,使得池中的空闲线程数可以动态的变化。创建一个线程后,立即此线程的ID存入m_ThreadList 和 m_IdleList队列中,通过调用fetchWork函数将自己置于阻塞状态。当workerQueue中没有任务等待执行,fetchWork执行sem_wait()即处于阻塞状态。当有新的任务加入到workerQueue 中,availableWork 信号执行一次 sem_post操作,唤醒一个空闲线程。线程被唤醒后,其ID号被添加到 m_BusyList队列中,执行完任务后,ID号在 m_BusyList队列中被删除,再添加到 m_IdleList 队列中。
 
  应用程序所创建的线程总数不能超过m_MaxNum,池中的线程总数不高于m_MaxNum时,空闲线程维持在 m_AvailLow之上线程池linux,同样,当空闲线程数高于m_AvailHigh时,程序会自动销毁一些线程,使空闲线程数目维持在一个合理的范围内。
 
  调用的实现方法如下:
 
  int main(int argc, char **argv)
 
  {
 
  ThreadPool* myPool = new ThreadPool(20);
 
  myPool->initializeThreads();
 
  //We will count time elapsed after initializeThreads()
 
  time_tt1=time(NULL);
 
  //Lets start bullying ThreadPool with tonnes of work !!!
 
  for(unsignedint i=0;i<ITERATIONS;i ){
 
  SampleWorkerThread* myThread = new SampleWorkerThread(i);
 
  cout << "myThread["<< myThread->id<< "] = ["<< myThread<< "]"<< endl;
 
  myPool->assignWork(myThread);
 
  }
 
  sleep(10);
 
  for(unsigned int i=0;i<ITERATIONS;i ){
 
  SampleWorkerThread* myThread = new SampleWorkerThread(i);
 
  cout << "myThread["<< myThread->id<< "] = ["<< myThread<< "]"<< endl;
 
  myPool->assignWork(myThread);
 
  }
 
  sleep(10);
 
  myPool->destroyPool(2);
 
  time_t t2=time(NULL);
 
  cout<< t2-t1<< " seconds elapsed\n"<< endl;
 
  deletemyPool;
 
  return0;
 
  }
 
  通过这个测试程序,我们可以看到池中的线程数动态的变化。
 
  ThreadPool的实现代码过长,受篇幅限制不便于发表,如有需要可以留言。
 

(编辑:我爱制作网_沈阳站长网)

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