http://blog.csdn.net/qq_25425023/article/details/53914609

线程池中的线程,在任务队列为空的时候,等待任务的到来,任务队列中有任务时,则依次获取任务来执行,任务队列需要同步。

Linux线程同步有多种方法:互斥量、信号量、条件变量等。

下面是根据互斥量、信号量、条件变量封装的三个类。

线程池中用到了互斥量和信号量。

[cpp] view plain copy
  1. #ifndef _LOCKER_H_
  2. #define _LOCKER_H_
  3. #include <pthread.h>
  4. #include <stdio.h>
  5. #include <semaphore.h>
  6. /*信号量的类*/
  7. class sem_locker
  8. {
  9. private:
  10. sem_t m_sem;
  11. public:
  12. //初始化信号量
  13. sem_locker()
  14. {
  15. if(sem_init(&m_sem, 0, 0) != 0)
  16. printf("sem init error\n");
  17. }
  18. //销毁信号量
  19. ~sem_locker()
  20. {
  21. sem_destroy(&m_sem);
  22. }
  23. //等待信号量
  24. bool wait()
  25. {
  26. return sem_wait(&m_sem) == 0;
  27. }
  28. //添加信号量
  29. bool add()
  30. {
  31. return sem_post(&m_sem) == 0;
  32. }
  33. };
  34. /*互斥 locker*/
  35. class mutex_locker
  36. {
  37. private:
  38. pthread_mutex_t m_mutex;
  39. public:
  40. mutex_locker()
  41. {
  42. if(pthread_mutex_init(&m_mutex, NULL) != 0)
  43. printf("mutex init error!");
  44. }
  45. ~mutex_locker()
  46. {
  47. pthread_mutex_destroy(&m_mutex);
  48. }
  49. bool mutex_lock()  //lock mutex
  50. {
  51. return pthread_mutex_lock(&m_mutex) == 0;
  52. }
  53. bool mutex_unlock()   //unlock
  54. {
  55. return pthread_mutex_unlock(&m_mutex) == 0;
  56. }
  57. };
  58. /*条件变量 locker*/
  59. class cond_locker
  60. {
  61. private:
  62. pthread_mutex_t m_mutex;
  63. pthread_cond_t m_cond;
  64. public:
  65. // 初始化 m_mutex and m_cond
  66. cond_locker()
  67. {
  68. if(pthread_mutex_init(&m_mutex, NULL) != 0)
  69. printf("mutex init error");
  70. if(pthread_cond_init(&m_cond, NULL) != 0)
  71. {   //条件变量初始化是被,释放初始化成功的mutex
  72. pthread_mutex_destroy(&m_mutex);
  73. printf("cond init error");
  74. }
  75. }
  76. // destroy mutex and cond
  77. ~cond_locker()
  78. {
  79. pthread_mutex_destroy(&m_mutex);
  80. pthread_cond_destroy(&m_cond);
  81. }
  82. //等待条件变量
  83. bool wait()
  84. {
  85. int ans = 0;
  86. pthread_mutex_lock(&m_mutex);
  87. ans = pthread_cond_wait(&m_cond, &m_mutex);
  88. pthread_mutex_unlock(&m_mutex);
  89. return ans == 0;
  90. }
  91. //唤醒等待条件变量的线程
  92. bool signal()
  93. {
  94. return pthread_cond_signal(&m_cond) == 0;
  95. }
  96. };
  97. #endif

下面的是线程池类,是一个模版类:

[cpp] view plain copy
  1. #ifndef _PTHREAD_POOL_
  2. #define _PTHREAD_POOL_
  3. #include "locker.h"
  4. #include <list>
  5. #include <stdio.h>
  6. #include <exception>
  7. #include <errno.h>
  8. #include <pthread.h>
  9. #include <iostream>
  10. template<class T>
  11. class threadpool
  12. {
  13. private:
  14. int thread_number;  //线程池的线程数
  15. int max_task_number;  //任务队列中的最大任务数
  16. pthread_t *all_threads;   //线程数组
  17. std::list<T *> task_queue; //任务队列
  18. mutex_locker queue_mutex_locker;  //互斥锁
  19. sem_locker queue_sem_locker;   //信号量
  20. bool is_stop; //是否结束线程
  21. public:
  22. threadpool(int thread_num = 20, int max_task_num = 30);
  23. ~threadpool();
  24. bool append_task(T *task);
  25. void start();
  26. void stop();
  27. private:
  28. //线程运行的函数。执行run()函数
  29. static void *worker(void *arg);
  30. void run();
  31. };
  32. template <class T>
  33. threadpool<T>::threadpool(int thread_num, int max_task_num):
  34. thread_number(thread_num), max_task_number(max_task_num),
  35. is_stop(false), all_threads(NULL)
  36. {
  37. if((thread_num <= 0) || max_task_num <= 0)
  38. printf("threadpool can't init because thread_number = 0"
  39. " or max_task_number = 0");
  40. all_threads = new pthread_t[thread_number];
  41. if(!all_threads)
  42. printf("can't init threadpool because thread array can't new");
  43. }
  44. template <class T>
  45. threadpool<T>::~threadpool()
  46. {
  47. delete []all_threads;
  48. is_stop = true;
  49. }
  50. template <class T>
  51. void threadpool<T>::stop()
  52. {
  53. is_stop = true;
  54. //queue_sem_locker.add();
  55. }
  56. template <class T>
  57. void threadpool<T>::start()
  58. {
  59. for(int i = 0; i < thread_number; ++i)
  60. {
  61. printf("create the %dth pthread\n", i);
  62. if(pthread_create(all_threads + i, NULL, worker, this) != 0)
  63. {//创建线程失败,清除成功申请的资源并抛出异常
  64. delete []all_threads;
  65. throw std::exception();
  66. }
  67. if(pthread_detach(all_threads[i]))
  68. {//将线程设置为脱离线程,失败则清除成功申请的资源并抛出异常
  69. delete []all_threads;
  70. throw std::exception();
  71. }
  72. }
  73. }
  74. //添加任务进入任务队列
  75. template <class T>
  76. bool threadpool<T>::append_task(T *task)
  77. {   //获取互斥锁
  78. queue_mutex_locker.mutex_lock();
  79. //判断队列中任务数是否大于最大任务数
  80. if(task_queue.size() > max_task_number)
  81. {//是则释放互斥锁
  82. queue_mutex_locker.mutex_unlock();
  83. return false;
  84. }
  85. //添加进入队列
  86. task_queue.push_back(task);
  87. queue_mutex_locker.mutex_unlock();
  88. //唤醒等待任务的线程
  89. queue_sem_locker.add();
  90. return true;
  91. }
  92. template <class T>
  93. void *threadpool<T>::worker(void *arg)
  94. {
  95. threadpool *pool = (threadpool *)arg;
  96. pool->run();
  97. return pool;
  98. }
  99. template <class T>
  100. void threadpool<T>::run()
  101. {
  102. while(!is_stop)
  103. {   //等待任务
  104. queue_sem_locker.wait();
  105. if(errno == EINTR)
  106. {
  107. printf("errno");
  108. continue;
  109. }
  110. //获取互斥锁
  111. queue_mutex_locker.mutex_lock();
  112. //判断任务队列是否为空
  113. if(task_queue.empty())
  114. {
  115. queue_mutex_locker.mutex_unlock();
  116. continue;
  117. }
  118. //获取队头任务并执行
  119. T *task = task_queue.front();
  120. task_queue.pop_front();
  121. queue_mutex_locker.mutex_unlock();
  122. if(!task)
  123. continue;
  124. //  printf("pthreadId = %ld\n", (unsigned long)pthread_self());
  125. task->doit();  //doit是T对象中的方法
  126. }
  127. //测试用
  128. printf("close %ld\n", (unsigned long)pthread_self());
  129. }
  130. #endif

以上参考《Linux高性能服务器编程》

写个程序对线程池进行测试:

[cpp] view plain copy
  1. #include <stdio.h>
  2. #include <iostream>
  3. #include <unistd.h>
  4. #include "thread_pool.h"
  5. class task
  6. {
  7. private:
  8. int number;
  9. public:
  10. task(int num) : number(num)
  11. {
  12. }
  13. ~task()
  14. {
  15. }
  16. void doit()
  17. {
  18. printf("this is the %dth task\n", number);
  19. }
  20. };
  21. int main()
  22. {
  23. task *ta;
  24. threadpool<task> pool(10, 15);
  25. //    pool.start();
  26. for(int i = 0; i < 20; ++i)
  27. {
  28. ta = new task(i);
  29. //  sleep(2);
  30. pool.append_task(ta);
  31. }
  32. pool.start();
  33. sleep(10);
  34. printf("close the thread pool\n");
  35. pool.stop();
  36. pause();
  37. return 0;
  38. }

经测试,线程池可以正常使用。

下一篇博客,使用线程池来实现回射服务器,测试可以达到多大的并发量。

Linux C++ 实现线程池相关推荐

  1. Linux下通用线程池的创建与使用

    Linux下通用线程池的创建与使用 本文给出了一个通用的线程池框架,该框架将与线程执行相关的任务进行了高层次的抽象,使之与具体的执行任务无关.另外该线程池具有动态伸缩性,它能根据执行任务的轻重自动调整 ...

  2. 【C++学习】 基于Linux/C++简单线程池的实现

    [C++学习] 基于Linux/C++简单线程池的实现 转载自:https://www.cnblogs.com/alwayswangzi/p/7138154.html 我们知道Java语言对于多线程的 ...

  3. 一个Linux下C线程池的实现

    什么时候需要创建线程池呢?简单的说,如果一个应用需要频繁的创建和销毁线程,而任务执行的时间又非常短,这样线程创建和销毁的带来的开销就不容忽 视,这时也是线程池该出场的机会了.如果线程创建和销毁时间相比 ...

  4. 一个Linux下C线程池的实现(转)

    1.线程池基本原理 在传统服务器结构中, 常是 有一个总的 监听线程监听有没有新的用户连接服务器, 每当有一个新的 用户进入, 服务器就开启一个新的线程用户处理这 个用户的数据包.这个线程只服务于这个 ...

  5. 【Linux练习生】线程池

    本节知识所需代码已同步到gitee-> https://gitee.com/ZMZZZhao/linux-git/tree/master/thread_pool 本文收录于专栏:Linux 关注 ...

  6. 简述Linux C下线程池的使用

    线程池也是多线程的处理方式.是将"生产者"线程提出任务添加到"任务队列",然后一些线程自动完成"任务队列"上的任务. 多线程编程,创建一个线 ...

  7. Linux下简单线程池的实现

    线程池的技术背景 在面向对象编程中,创建和销毁对象是很费时间的,因为创建一个对象要获取内存资源或者其它更多资源.在Java中更是如此,虚拟机将试图跟踪每一个对象,以便能够在对象销毁后进行垃圾回收.所以 ...

  8. Linux系统编程——线程池

    http://blog.csdn.net/tennysonsky/article/details/46490099# 线程池基本原理 在传统服务器结构中,常是有一个总的监听线程监听有没有新的用户连接服 ...

  9. linux进程池 自动增长,linux下C 线程池的原理讲解和代码实现(能自行伸缩扩展线程数)...

    什么线程池,为什么要使用线程池?下面是一个比喻. 阶段一.一个医院,每天面对成千上万的病人,处理方式是:来一个病人找来一个医生处理,处理完了医生也走了.当看病时间较短的时候,医生来去的时间,显得尤为费 ...

最新文章

  1. 12.Linux:exec函数族
  2. hive 判断子字符串_Java中检查空字符串(null或空白)的方法有几种?
  3. redis实现简单限流
  4. ”盒模型“之如何防止边框和内边距把元素撑开
  5. 2020 从新开始:你应该知道的Oracle认证新变化
  6. eclipse的简介安装与配置
  7. 量子计算机接口,量子计算机接口架构设计与研究
  8. SQL存储过程与自定义函数实例
  9. USB免驱NFC读写器 Android系统中NFC读写范例
  10. 做了一款股票复盘工具
  11. Qt日历控件显示周数为:日一二三四五六
  12. 用PS设计曲线四分环
  13. Python爬虫之堆糖网图片(二)
  14. Linux PCI驱动编写
  15. ROS Noetic KDL与TracIk安装
  16. 【C】有一个已排好序的数组,要求输入一个数后,按原来排序的规律将它插入数组中
  17. 求薪水最高的第6到第10个人
  18. 2020 计蒜客蓝桥杯省赛 B 组模拟赛(一)题解4.苹果
  19. davinci平台Uboot移植
  20. 共享内存shmget传输数据

热门文章

  1. 大龄程序员怎样渡过中年危机?(转)
  2. 模型和控制器-起步阶段
  3. MarshalHelper
  4. Extjs TextField扩展
  5. php读取xml标签内容,从xml php5获取内容
  6. oracle事务提交前更新机制,Oracle 事务机制 批量添加,修改,更新
  7. java list 循环赋值_Java List集合的坑(add方法报空指针,循环赋值时list已保存的值会改变)...
  8. js实现oss批量下载文件_js下载文件到本地各种方法总结
  9. 名为 cursor_jinserted 的游标不存在_生鲜电商存在的问题及对策解析:未来生鲜电商如何发展?...
  10. java自定义分页标签_自定义分页标签--仿javaeye分页效果