0


【linux多线程(四)】——线程池的详细解析(含代码)


【linux线程(壹)】——初识线程(区分线程和进程,线程创建的基本操作)
【线程(二)】——互斥量的详细解析
【线程(三)】———条件变量的详细解析

什么是线程池?

线程池是一种线程使用模式,它是将一定数量线程和缓冲队列预存在一个池子中,池子中的线程轮流的往任务队列中拿去任务并完成任务,而任务队列往外开发一个接口,使其他线程能够往任务队列中推送任务。

线程池的优点:

线程池能够减少线程的创建和销毁所消耗的时间和系统资源的开销,如果不使用线程池,将可能造成系统创建大量的同类线程而导致消耗完内存或“过度切换”的问题。

线程池的应用场景

1,需要大量线程来完成任务,且完成任务的时间较短,WEB服务器完成网页请求这样的任务使用线程池技术是非常合适的。因为单个任务小,而任务数量巨大,但对于长时间的任务,比如一个Telnet连接请求,线程池的优点不明显,因为Telnet会话时间比线程的创建时间太多了。

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

3.接受突发的大量请求时,但不至于使服务器创建大量的线程,在没有线程池情况下,将产生大量的线程,短时间内会产生大量的线程可能使内存达到极限,出现错误。

线程池的实现

线程池的成员变量:

  • 任务队列,quueu<T> q;
  • 线程个数,int num;
  • 互斥量,pthread_mutex_t lock;
  • 条件变量,pthread_cond_t cond;

创建线程池,需要创建一个任务队列和一定数量的线程。由于每次只能有一个线程进入队列中放任务和拿任务,所以此时需要定义一个互斥量进行维护,如果任务队列中的没有任务,此时线程就不能进入任务队列中,所以就创建一个条件变量。

线程池的代码(C++)

** makefile文件**

  1. threadpool:threadpool.cc
  2. g++ $^ -o $@ -lpthread
  3. clean:
  4. rm -f threadpool

Task.hpp文件

  1. #pragma once
  2. #include<iostream>
  3. #include<stdio.h>
  4. using namespace std;
  5. class Task
  6. {
  7. private:
  8. int x;int y;
  9. char op;
  10. public:
  11. Task(int _x,int _y,char _op)
  12. :x(_x)
  13. ,y(_y)
  14. ,op(_op){ }
  15. Task()
  16. {};
  17. void Run()
  18. {
  19. int ret=0;
  20. switch(op){
  21. case '+':
  22. ret=x+y;
  23. break;
  24. case '-':
  25. ret=x-y;
  26. break;
  27. case '*':
  28. ret=x*y;
  29. break;
  30. case '/':
  31. ret=x/y;
  32. break;
  33. case '%':
  34. ret=x%y;
  35. break;
  36. }
  37. printf("%d %c %d = %d\n",x,op,y,ret);
  38. }
  39. };

** threadpool.hpp文件 **

  1. #pragma once
  2. #include<iostream>
  3. #include<queue>
  4. #include<pthread.h>
  5. #include<unistd.h>
  6. using namespace std;
  7. #define NUM 4
  8. template<class T>
  9. class ThreadPool
  10. {
  11. private:
  12. queue<T> q;//任务队列
  13. int thread_num;//线程池的线程数量
  14. pthread_mutex_t lock;//互斥锁
  15. pthread_cond_t cond;//条件变量
  16. public:
  17. ThreadPool(int num=NUM)//初始化变量
  18. :thread_num(num){
  19. pthread_mutex_init(&lock,NULL);
  20. pthread_cond_init(&cond,NULL);
  21. }
  22. bool Empty()
  23. {
  24. return q.size()==0?true:false;
  25. }
  26. static void* Routine(void* arg)//线程执行流
  27. {
  28. pthread_detach(pthread_self());//线程分离
  29. ThreadPool* self=(ThreadPool*)arg;
  30. while(1)
  31. {
  32. self->LockQueue();
  33. while(self->Empty())//任务队列是否为空
  34. {
  35. self->Wait();
  36. }
  37. T data;
  38. self->Pop(data);//取出任务
  39. self->UnlockQueue();
  40. cout<<pthread_self()<<"# ";
  41. //处理任务
  42. data.Run();//处理任务
  43. sleep(1);
  44. }
  45. }
  46. void Wait()//线程等待
  47. {
  48. pthread_cond_wait(&cond,&lock);
  49. }
  50. void LockQueue()//锁住队列
  51. {
  52. pthread_mutex_lock(&lock);
  53. }
  54. void UnlockQueue()//解锁队列
  55. {
  56. pthread_mutex_unlock(&lock);
  57. }
  58. void ThreadPoolInit()
  59. {
  60. pthread_t tid;
  61. for(int i=0;i<thread_num;i++)//创建线程池中的线程
  62. {
  63. pthread_create(&tid,NULL,Routine,(void*)this);
  64. }
  65. }
  66. void Push(const T& in)//将任务推进任务队列中
  67. {
  68. LockQueue();
  69. q.push(in);
  70. UnlockQueue();
  71. SignalThread();
  72. }
  73. void SignalThread()//唤醒cond变量下的线程
  74. {
  75. pthread_cond_signal(&cond);
  76. }
  77. void Pop( T& out)//取出任务队列中的任务
  78. {
  79. out=q.front();
  80. q.pop();
  81. }
  82. ~ThreadPool()
  83. {
  84. pthread_mutex_destroy(&lock);
  85. pthread_cond_destroy(&cond);
  86. }
  87. };

threadpool.cc 文件

  1. #include"threadpool.hpp"
  2. #include"Task.hpp"
  3. #include<time.h>
  4. #include<stdlib.h>
  5. int main()
  6. {
  7. ThreadPool<Task> * q=new ThreadPool<Task>();//创建线程池
  8. q->ThreadPoolInit();
  9. srand((long int)time(NULL));
  10. while(1) //主线程往任务队列中放任务
  11. {
  12. char arr[]="+-*/%";
  13. int x=rand()%100+1;
  14. int y=rand()%100+1;
  15. char op=arr[rand()%5];
  16. Task t(x,y,op);//创建任务
  17. q->Push(t);//将任务推送给队列中
  18. }
  19. return 0;
  20. }

运行结果:

标签: linux 运维 服务器

本文转载自: https://blog.csdn.net/sjp11/article/details/122914857
版权归原作者 努力学习的少年 所有, 如有侵权,请联系我们删除。

“【linux多线程(四)】&mdash;&mdash;线程池的详细解析(含代码)”的评论:

还没有评论