线程池的实现与应用

  金牌会员 | 2024-11-22 11:23:53 | 显示全部楼层 | 阅读模式
打印 上一主题 下一主题

主题 806|帖子 806|积分 2418

一、线程池

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

1. 需要大量的线程来完成任务,且完成任务的时间比较短。WEB服务器完成网页请求如许的任务,使用线程池技术黑白常合适的。因为单个任务小,而任务数目巨大,你可以想象一个热门网站的点击次数。但对于长时间的任务,比如一个 Telnet毗连请求,线程池的优点就不明显了。因为Telnet会话时间比线程的创建时间大多了。
2. 对性能要求苛刻的应用,比如要求服务器敏捷相应客户请求。
3. 担当突发性的大量请求,但不至于使服务器因此产生大量线程的应用。突发性大量客户请求,在没有线程池环境下,将产生大量线程,虽然理论上大部分操纵体系线程数目最大值不是题目,短时间内产生大量线程可能使内存到达极限,出现错误.
4.线程池示例:
1. 创建固定命量线程池,循环从任务队列中获取任务对象,
2. 获取到任务对象后,执行任务对象中的任务接口.

三、代码

主线程发布任务,多线程获得任务,执行任务
(1)任务
  1. Task.hpp
  2. #pragma once
  3. #include <iostream>
  4. #include <string>
  5. std::string opers="+-*/%";
  6. enum{
  7.     DivZero=1,
  8.     ModZero,
  9.     Unknown
  10. };
  11. class Task
  12. {
  13. public:
  14.     Task(int x, int y, char op) : data1_(x), data2_(y), oper_(op), result_(0), exitcode_(0)
  15.     {
  16.     }
  17.     void run()
  18.     {
  19.         switch (oper_)
  20.         {
  21.         case '+':
  22.             result_ = data1_ + data2_;
  23.             break;
  24.         case '-':
  25.             result_ = data1_ - data2_;
  26.             break;
  27.         case '*':
  28.             result_ = data1_ * data2_;
  29.             break;
  30.         case '/':
  31.             {
  32.                 if(data2_ == 0) exitcode_ = DivZero;
  33.                 else result_ = data1_ / data2_;
  34.             }
  35.             break;
  36.         case '%':
  37.            {
  38.                 if(data2_ == 0) exitcode_ = ModZero;
  39.                 else result_ = data1_ % data2_;
  40.             }            break;
  41.         default:
  42.             exitcode_ = Unknown;
  43.             break;
  44.         }
  45.     }
  46.     void operator ()()
  47.     {
  48.         run();
  49.     }
  50.     std::string GetResult()
  51.     {
  52.         std::string r = std::to_string(data1_);
  53.         r += oper_;
  54.         r += std::to_string(data2_);
  55.         r += "=";
  56.         r += std::to_string(result_);
  57.         r += "[code: ";
  58.         r += std::to_string(exitcode_);
  59.         r += "]";
  60.         return r;
  61.     }
  62.     std::string GetTask()
  63.     {
  64.         std::string r = std::to_string(data1_);
  65.         r += oper_;
  66.         r += std::to_string(data2_);
  67.         r += "=?";
  68.         return r;
  69.     }
  70.     ~Task()
  71.     {
  72.     }
  73. private:
  74.     int data1_;
  75.     int data2_;
  76.     char oper_;
  77.     int result_;
  78.     int exitcode_;
  79. };
复制代码
(2)线程池
  1. #pragma once
  2. #include <iostream>
  3. #include<vector>
  4. #include<string>
  5. #include<pthread.h>
  6. #include<queue>
  7. struct ThreadInfo
  8. {
  9.     pthread_t tid;
  10.     std::string name;
  11. };
  12. static const int deafultnum=5; //默认多少个线程
  13. template <class T>
  14. class ThreadPool
  15. {
  16. public:
  17.     void Lock()
  18.     {
  19.         pthread_mutex_lock(&mutex_);
  20.     }
  21.     void Unlock()
  22.     {
  23.         pthread_mutex_unlock(&mutex_);
  24.     }
  25.     void Wakeup()//线程唤醒
  26.     {
  27.         pthread_cond_signal(&cond_);
  28.     }
  29.     void ThreadSleep() //线程休眠
  30.     {
  31.         pthread_cond_wait(&cond_, &mutex_);
  32.     }
  33.     bool IsQueueEmpty()
  34.     {
  35.         return tasks_.empty();
  36.     }
  37.     std::string GetThreadName(pthread_t tid)
  38.     {
  39.         for (const auto &ti : threads_)
  40.         {
  41.             if (ti.tid == tid)
  42.                 return ti.name;
  43.         }
  44.         return "None";
  45.     }
  46. public:
  47.     ThreadPool(int num=deafultnum):threads_(num)
  48.     {
  49.         pthread_mutex_init(&mutex_,nullptr);
  50.         pthread_cond_init(&cond_,nullptr);
  51.     }
  52.     static void *HandleTask(void *args) //所有线程启动后,就会去检测有没有任务,有任务就执行,没任务就休眠
  53.     {
  54.         ThreadPool<T> *tp=static_cast<ThreadPool<T>*>(args);
  55.         std::string name=tp->GetThreadName(pthread_self());
  56.         while (true)
  57.         {
  58.             tp->Lock();
  59.             while(tp->IsQueueEmpty())
  60.             {
  61.                 tp->ThreadSleep();
  62.             }
  63.             T t=tp->pop();
  64.             tp->Unlock();
  65.             //当你拿到这个任务,这个任务就是属于你,你不需要在加锁,解锁之间。
  66.             t();
  67.             std::cout<<name<<"run,"<<"result:"<<t.GetResult()<<std::endl;
  68.         }
  69.     }
  70.     void start()
  71.     {
  72.         int num=threads_.size();
  73.         for(int i=0;i<num;i++)
  74.         {
  75.             threads_[i].name="thread-"+std::to_string(i+1);
  76.             pthread_create(&(threads_[i].tid),nullptr,HandleTask,this);
  77.         }
  78.     }
  79.     T pop()
  80.     {
  81.         T t=tasks_.front();
  82.         tasks_.pop();
  83.         return t;
  84.     }
  85.     void push(const T &t)//往线程池中放任务之后线程才能执行任务
  86.     {
  87.         Lock();
  88.         tasks_.push(t); //有任务,线程别睡了
  89.         Wakeup();
  90.         Unlock();
  91.     }
  92.     ~ThreadPool()
  93.     {
  94.         pthread_mutex_destroy(&mutex_);
  95.         pthread_cond_destroy(&cond_);
  96.     }
  97. private:
  98.     std::vector<ThreadInfo> threads_; //这是个vector容器,表示有多少个线程
  99.     std::queue<T> tasks_;
  100.     pthread_mutex_t mutex_;
  101.     pthread_cond_t cond_;
  102. };
复制代码
 (3)主函数
  1. #include <iostream>
  2. #include "ThreadPool.hpp"
  3. #include "Task.hpp"
  4. #include  <unistd.h>
  5. int main()
  6. {
  7.     ThreadPool<Task> *tp=new ThreadPool<Task>(5);
  8.     tp->start();
  9.     srand(time(nullptr) ^ getpid());
  10.     while(true)
  11.     {
  12.         //1.构建任务
  13.         int x = rand() % 10 + 1;
  14.         usleep(10);
  15.         int y = rand() % 5;
  16.         char op = opers[rand()%opers.size()];
  17.         Task t(x, y, op);
  18.         tp->push(t);
  19.         //ThreadPool<Task>::GetInstance()->Push(t);
  20.         //2.交给线程池处理
  21.         std::cout << "main thread make task: " << t.GetTask() << std::endl;
  22.         sleep(1);
  23.     }
  24. }
复制代码
(4)执行效果
 

 

 

免责声明:如果侵犯了您的权益,请联系站长,我们会及时删除侵权内容,谢谢合作!更多信息从访问主页:qidao123.com:ToB企服之家,中国第一个企服评测及商务社交产业平台。
回复

使用道具 举报

0 个回复

倒序浏览

快速回复

您需要登录后才可以回帖 登录 or 立即注册

本版积分规则

金牌会员
这个人很懒什么都没写!

标签云

快速回复 返回顶部 返回列表