Linux C++ 实现线程池
http://blog.csdn.net/qq_25425023/article/details/53914609
线程池中的线程,在任务队列为空的时候,等待任务的到来,任务队列中有任务时,则依次获取任务来执行,任务队列需要同步。
Linux线程同步有多种方法:互斥量、信号量、条件变量等。
下面是根据互斥量、信号量、条件变量封装的三个类。
线程池中用到了互斥量和信号量。
- #ifndef _LOCKER_H_
- #define _LOCKER_H_
- #include <pthread.h>
- #include <stdio.h>
- #include <semaphore.h>
- /*信号量的类*/
- class sem_locker
- {
- private:
- sem_t m_sem;
- public:
- //初始化信号量
- sem_locker()
- {
- if(sem_init(&m_sem, 0, 0) != 0)
- printf("sem init error\n");
- }
- //销毁信号量
- ~sem_locker()
- {
- sem_destroy(&m_sem);
- }
- //等待信号量
- bool wait()
- {
- return sem_wait(&m_sem) == 0;
- }
- //添加信号量
- bool add()
- {
- return sem_post(&m_sem) == 0;
- }
- };
- /*互斥 locker*/
- class mutex_locker
- {
- private:
- pthread_mutex_t m_mutex;
- public:
- mutex_locker()
- {
- if(pthread_mutex_init(&m_mutex, NULL) != 0)
- printf("mutex init error!");
- }
- ~mutex_locker()
- {
- pthread_mutex_destroy(&m_mutex);
- }
- bool mutex_lock() //lock mutex
- {
- return pthread_mutex_lock(&m_mutex) == 0;
- }
- bool mutex_unlock() //unlock
- {
- return pthread_mutex_unlock(&m_mutex) == 0;
- }
- };
- /*条件变量 locker*/
- class cond_locker
- {
- private:
- pthread_mutex_t m_mutex;
- pthread_cond_t m_cond;
- public:
- // 初始化 m_mutex and m_cond
- cond_locker()
- {
- if(pthread_mutex_init(&m_mutex, NULL) != 0)
- printf("mutex init error");
- if(pthread_cond_init(&m_cond, NULL) != 0)
- { //条件变量初始化是被,释放初始化成功的mutex
- pthread_mutex_destroy(&m_mutex);
- printf("cond init error");
- }
- }
- // destroy mutex and cond
- ~cond_locker()
- {
- pthread_mutex_destroy(&m_mutex);
- pthread_cond_destroy(&m_cond);
- }
- //等待条件变量
- bool wait()
- {
- int ans = 0;
- pthread_mutex_lock(&m_mutex);
- ans = pthread_cond_wait(&m_cond, &m_mutex);
- pthread_mutex_unlock(&m_mutex);
- return ans == 0;
- }
- //唤醒等待条件变量的线程
- bool signal()
- {
- return pthread_cond_signal(&m_cond) == 0;
- }
- };
- #endif
下面的是线程池类,是一个模版类:
- #ifndef _PTHREAD_POOL_
- #define _PTHREAD_POOL_
- #include "locker.h"
- #include <list>
- #include <stdio.h>
- #include <exception>
- #include <errno.h>
- #include <pthread.h>
- #include <iostream>
- template<class T>
- class threadpool
- {
- private:
- int thread_number; //线程池的线程数
- int max_task_number; //任务队列中的最大任务数
- pthread_t *all_threads; //线程数组
- std::list<T *> task_queue; //任务队列
- mutex_locker queue_mutex_locker; //互斥锁
- sem_locker queue_sem_locker; //信号量
- bool is_stop; //是否结束线程
- public:
- threadpool(int thread_num = 20, int max_task_num = 30);
- ~threadpool();
- bool append_task(T *task);
- void start();
- void stop();
- private:
- //线程运行的函数。执行run()函数
- static void *worker(void *arg);
- void run();
- };
- template <class T>
- threadpool<T>::threadpool(int thread_num, int max_task_num):
- thread_number(thread_num), max_task_number(max_task_num),
- is_stop(false), all_threads(NULL)
- {
- if((thread_num <= 0) || max_task_num <= 0)
- printf("threadpool can't init because thread_number = 0"
- " or max_task_number = 0");
- all_threads = new pthread_t[thread_number];
- if(!all_threads)
- printf("can't init threadpool because thread array can't new");
- }
- template <class T>
- threadpool<T>::~threadpool()
- {
- delete []all_threads;
- is_stop = true;
- }
- template <class T>
- void threadpool<T>::stop()
- {
- is_stop = true;
- //queue_sem_locker.add();
- }
- template <class T>
- void threadpool<T>::start()
- {
- for(int i = 0; i < thread_number; ++i)
- {
- printf("create the %dth pthread\n", i);
- if(pthread_create(all_threads + i, NULL, worker, this) != 0)
- {//创建线程失败,清除成功申请的资源并抛出异常
- delete []all_threads;
- throw std::exception();
- }
- if(pthread_detach(all_threads[i]))
- {//将线程设置为脱离线程,失败则清除成功申请的资源并抛出异常
- delete []all_threads;
- throw std::exception();
- }
- }
- }
- //添加任务进入任务队列
- template <class T>
- bool threadpool<T>::append_task(T *task)
- { //获取互斥锁
- queue_mutex_locker.mutex_lock();
- //判断队列中任务数是否大于最大任务数
- if(task_queue.size() > max_task_number)
- {//是则释放互斥锁
- queue_mutex_locker.mutex_unlock();
- return false;
- }
- //添加进入队列
- task_queue.push_back(task);
- queue_mutex_locker.mutex_unlock();
- //唤醒等待任务的线程
- queue_sem_locker.add();
- return true;
- }
- template <class T>
- void *threadpool<T>::worker(void *arg)
- {
- threadpool *pool = (threadpool *)arg;
- pool->run();
- return pool;
- }
- template <class T>
- void threadpool<T>::run()
- {
- while(!is_stop)
- { //等待任务
- queue_sem_locker.wait();
- if(errno == EINTR)
- {
- printf("errno");
- continue;
- }
- //获取互斥锁
- queue_mutex_locker.mutex_lock();
- //判断任务队列是否为空
- if(task_queue.empty())
- {
- queue_mutex_locker.mutex_unlock();
- continue;
- }
- //获取队头任务并执行
- T *task = task_queue.front();
- task_queue.pop_front();
- queue_mutex_locker.mutex_unlock();
- if(!task)
- continue;
- // printf("pthreadId = %ld\n", (unsigned long)pthread_self());
- task->doit(); //doit是T对象中的方法
- }
- //测试用
- printf("close %ld\n", (unsigned long)pthread_self());
- }
- #endif
以上参考《Linux高性能服务器编程》
写个程序对线程池进行测试:
- #include <stdio.h>
- #include <iostream>
- #include <unistd.h>
- #include "thread_pool.h"
- class task
- {
- private:
- int number;
- public:
- task(int num) : number(num)
- {
- }
- ~task()
- {
- }
- void doit()
- {
- printf("this is the %dth task\n", number);
- }
- };
- int main()
- {
- task *ta;
- threadpool<task> pool(10, 15);
- // pool.start();
- for(int i = 0; i < 20; ++i)
- {
- ta = new task(i);
- // sleep(2);
- pool.append_task(ta);
- }
- pool.start();
- sleep(10);
- printf("close the thread pool\n");
- pool.stop();
- pause();
- return 0;
- }
经测试,线程池可以正常使用。
下一篇博客,使用线程池来实现回射服务器,测试可以达到多大的并发量。
Linux C++ 实现线程池相关推荐
- Linux下通用线程池的创建与使用
Linux下通用线程池的创建与使用 本文给出了一个通用的线程池框架,该框架将与线程执行相关的任务进行了高层次的抽象,使之与具体的执行任务无关.另外该线程池具有动态伸缩性,它能根据执行任务的轻重自动调整 ...
- 【C++学习】 基于Linux/C++简单线程池的实现
[C++学习] 基于Linux/C++简单线程池的实现 转载自:https://www.cnblogs.com/alwayswangzi/p/7138154.html 我们知道Java语言对于多线程的 ...
- 一个Linux下C线程池的实现
什么时候需要创建线程池呢?简单的说,如果一个应用需要频繁的创建和销毁线程,而任务执行的时间又非常短,这样线程创建和销毁的带来的开销就不容忽 视,这时也是线程池该出场的机会了.如果线程创建和销毁时间相比 ...
- 一个Linux下C线程池的实现(转)
1.线程池基本原理 在传统服务器结构中, 常是 有一个总的 监听线程监听有没有新的用户连接服务器, 每当有一个新的 用户进入, 服务器就开启一个新的线程用户处理这 个用户的数据包.这个线程只服务于这个 ...
- 【Linux练习生】线程池
本节知识所需代码已同步到gitee-> https://gitee.com/ZMZZZhao/linux-git/tree/master/thread_pool 本文收录于专栏:Linux 关注 ...
- 简述Linux C下线程池的使用
线程池也是多线程的处理方式.是将"生产者"线程提出任务添加到"任务队列",然后一些线程自动完成"任务队列"上的任务. 多线程编程,创建一个线 ...
- Linux下简单线程池的实现
线程池的技术背景 在面向对象编程中,创建和销毁对象是很费时间的,因为创建一个对象要获取内存资源或者其它更多资源.在Java中更是如此,虚拟机将试图跟踪每一个对象,以便能够在对象销毁后进行垃圾回收.所以 ...
- Linux系统编程——线程池
http://blog.csdn.net/tennysonsky/article/details/46490099# 线程池基本原理 在传统服务器结构中,常是有一个总的监听线程监听有没有新的用户连接服 ...
- linux进程池 自动增长,linux下C 线程池的原理讲解和代码实现(能自行伸缩扩展线程数)...
什么线程池,为什么要使用线程池?下面是一个比喻. 阶段一.一个医院,每天面对成千上万的病人,处理方式是:来一个病人找来一个医生处理,处理完了医生也走了.当看病时间较短的时候,医生来去的时间,显得尤为费 ...
最新文章
- 12.Linux:exec函数族
- hive 判断子字符串_Java中检查空字符串(null或空白)的方法有几种?
- redis实现简单限流
- ”盒模型“之如何防止边框和内边距把元素撑开
- 2020 从新开始:你应该知道的Oracle认证新变化
- eclipse的简介安装与配置
- 量子计算机接口,量子计算机接口架构设计与研究
- SQL存储过程与自定义函数实例
- USB免驱NFC读写器 Android系统中NFC读写范例
- 做了一款股票复盘工具
- Qt日历控件显示周数为:日一二三四五六
- 用PS设计曲线四分环
- Python爬虫之堆糖网图片(二)
- Linux PCI驱动编写
- ROS Noetic KDL与TracIk安装
- 【C】有一个已排好序的数组,要求输入一个数后,按原来排序的规律将它插入数组中
- 求薪水最高的第6到第10个人
- 2020 计蒜客蓝桥杯省赛 B 组模拟赛(一)题解4.苹果
- davinci平台Uboot移植
- 共享内存shmget传输数据
热门文章
- 大龄程序员怎样渡过中年危机?(转)
- 模型和控制器-起步阶段
- MarshalHelper
- Extjs TextField扩展
- php读取xml标签内容,从xml php5获取内容
- oracle事务提交前更新机制,Oracle 事务机制 批量添加,修改,更新
- java list 循环赋值_Java List集合的坑(add方法报空指针,循环赋值时list已保存的值会改变)...
- js实现oss批量下载文件_js下载文件到本地各种方法总结
- 名为 cursor_jinserted 的游标不存在_生鲜电商存在的问题及对策解析:未来生鲜电商如何发展?...
- java自定义分页标签_自定义分页标签--仿javaeye分页效果