【C/C++开发】C++实现简单的线程池
C++实现简单的线程池
线程池编程简介:
在我们的服务端的程序中运用了大量关于池的概念,线程池、连接池、内存池、对象池等等。使用池的概念后可以高效利用服务器端的资源,比如没有大量的线程在系统中进行上下文的切换,一个数据库连接池,也只需要维护一定里的连接,而不是占用很多数据库连接资源。同时它们也避免了一些耗时的操作,比如创建一个线程,申请一个数据库连接,而且可能就只使用那么一次,然后就立刻释放刚申请的资源,效率很低。
在我的上一篇blog中已经实现一个线程基类了,在这里我们只需要实现一个线程池类ThreadPool和该线程池调度的工作线程类WorkThread即可,而且WorkThread是继承自Thread类的。
实现思路:
一个简单的线程池的实现思路一般如下:
- 在ThreadPool中创建多个线程(WorkThreadk对象),每个线程均处于阻塞状态,等待任务的到来
- ThreadPool提供一个提交任务的接口,如post_job(ProcCallback func, void* data); post_job后会立即返回,不会阻塞
- ThreadPool维护一个空闲线程队列,当客户程序调用post_job()后,如果空闲队列中有空闲线程,则取出一个线程句柄,并设置任务再给出新任务通知事件即可,处理等待的线程捕捉到事件信号后便开始执行任务,执行完后将该线程句柄重新push到空闲线程队列中
- 该线程池采用回调函数方式
首先我们实现一个WorkThread类:
2 //由线程池调度的工作线程
3 class WorkThread : public Thread //Thread类的实现可参考我上一篇的blog: 《C++封装一个简单的线程类》
4 {
5 friend class ThreadPool;
6 public:
7 WorkThread(ThreadPool* pthr_pool)
8 {
9 thr_pool_ = pthr_pool;
10 cb_func_ = NULL;
11 param_ = NULL;
12 }
13 virtual ~WorkThread(){}
14 void set_job(ProcCallBack func, void* param)
15 {
16 cb_func_ = func;
17 param_ = param;
18 notify(); //通知有新的任务
19 }
20 //实现Thread的run方法,并调用用户指定的函数
21 virtual void run()
22 {
23 if (cb_func_)
24 cb_func_(param_);
25
26 //reset callback function pointer
27 cb_func_ = NULL;
28 param_ = NULL;
29
30 //执行完任务,将该线程句柄移到线程池空闲队列
31 thr_pool_->move_to_idle_que(this);
32 }
33
34 private:
35 ThreadPool* thr_pool_; //线程池指针
36 ProcCallBack cb_func_; //回调函数地址
37 void* param_; //回调函数参数
38 };
该WorkThread中,有一个回调函数指针和参数,当有新任务时,会在run()中被调用,执行完后会将该线程移动到空闲线程队列,等待下一次任务的提交。
ThreadPool类定义如下:
2 {
3 friend class WorkThread;
4 public:
5 ThreadPool();
6 virtual ~ThreadPool();
7 int start_thread_pool(size_t thread_num = 5); //启动thread_num个线程
8 int stop_thread_pool(); //线束线程池
9 void destroy(); //销毁线程池所申请的资源
10 void post_job(ProcCallBack func, void* data); //提交任务接口,传入回调函数地址和参数
11
12 protected:
13 WorkThread* get_idle_thread(); //从获得空闲队列中取得一个线程句柄
14 void append_idle_thread(WorkThread* pthread); //加入到thread_vec_和idl_que_中
15 void move_to_idle_que(WorkThread* idlethread); //将线程句柄加入到idle_que_中
16
17 private:
18 size_t thr_num_; //线程数目
19 vector<WorkThread*> thr_vec_; //线程句柄集合
20 BlockQueue<WorkThread*> idle_que_; //空闲线程队列
21
22 private:
23 // not implement
24 ThreadPool(const ThreadPool& );
25 ThreadPool& operator=(const ThreadPool& );
26 };
2 {
3 assert(thread_num != 0);
4 thr_num_ = thread_num;
5 int ret = 0;
6 for (size_t i = 0; i < thr_num_; ++i)
7 {
8 WorkThread* pthr = new WorkThread(this);
9 pthr->set_thread_id(i);
10 if ((ret = pthr->start()) != 0)
11 {
12 printf("start_thread_pool: failed when create a work thread: %d\n", i);
13 delete pthr;
14 return i;
15 }
16 append_idle_thread(pthr);
17 }
18 return thr_num_;
19 }
20 int ThreadPool::stop_thread_pool()
21 {
22 for (size_t i = 0; i < thr_vec_.size(); ++i)
23 {
24 WorkThread* pthr = thr_vec_[i];
25 pthr->join();
26 delete pthr;
27 }
28 thr_vec_.clear();
29 idle_que_.clear();
30 return 0;
31 }
32 void ThreadPool::destroy()
33 {
34 stop_thread_pool();
35 }
36 void ThreadPool::append_idle_thread(WorkThread* pthread)
37 {
38 thr_vec_.push_back(pthread);
39 idle_que_.push(pthread);
40 }
41 void ThreadPool::move_to_idle_que(WorkThread* idlethread)
42 {
43 idle_que_.push(idlethread);
44 }
45 WorkThread* ThreadPool::get_idle_thread()
46 {
47 WorkThread* pthr = NULL;
48 if (!idle_que_.empty())
49 pthr = idle_que_.take();
50 return pthr;
51 }
52 void ThreadPool::post_job(ProcCallBack func, void* data)
53 {
54 assert(func != NULL);
55 WorkThread* pthr = get_idle_thread();
56 while (pthr == NULL)
57 {
58 apr_sleep(500000);
59 pthr = get_idle_thread();
60 }
61 pthr->set_job(func, data);
62 }
转载于:https://www.cnblogs.com/huty/p/8517387.html
【C/C++开发】C++实现简单的线程池相关推荐
- 分享:一个简单的线程池的实现
一个简单的线程池的实现 http://my.oschina.net/hejiula/blog/110519
- 手写一个简单的线程池MyThreadPool
说明 手写的一个简单的线程池,旨在帮助了解线程池的工作原理. 核心内容 核心工作线程 任务阻塞队列 定义一个内部类去实现核心工作线程 /*** 内部类:工作的核心线程*/private final c ...
- C语言实现的简单的线程池
http://www.linuxidc.com/Linux/2013-01/77619.htm 有时我们会需要大量线程来处理一些相互独立的任务,为了避免频繁的申请释放线程所带来的开销,我们可以使用线程 ...
- 一个简单的线程池设计方案
一个简单的线程池本质上是生产者-消费者模型,一般是线程池负责消费任务,任务分配线程负责生产任务,任务可以由队列.链表或全局变量等数据结构承担.如果生产和消费速度差不多,可以采用环形队列结构:如果任务有 ...
- C语言实现简单的线程池【转】
转自https://blog.csdn.net/hubi0952/article/details/8045094 线程池的基本原理 在传统的服务器结构中,常用一个总的线程监听有没有新的客户端连接服务器 ...
- 实际开发什么场景用到线程池_线程池的具体业务场景分析
如今,通过线程池最大程度利用CPU的多核性能是十分常见的基础操作.与此同时线程池的优势是显而易见的,它可以降低系统资源消耗,提高系统响应速度,方便线程并发数的管控等等.那么线程池的实现是怎么样的呢?本 ...
- 简单C++线程池包装类源码示例
这里给出一个简单的C++线程池包装类,该类具有的特点是: 1.线程池大小是固定的, 一创建后,就不具有伸缩特性. 一般建议是 CPU核心数的2倍或1倍. 2.简单但是很可靠. 3.资源占用极低. 在开 ...
- java基础:简单实现线程池
先上原理图:为了更好的在手机上显示,我重新把图画了一遍 上代码之前,要先补充一下线程池构造的核心几个点 线程池里的核心线程数与最大线程数 线程池里真正工作的线程worker 线程池里用来存取任务的队列 ...
- android的线程管理器,[Android开源]:一款安全、轻巧、简单的线程池管理器EasyThread...
EasyThread通过对原生的线程池进行封装,可让你更方便的进行线程任务操作. 特性 简单轻巧:方法数不过百,无额外次级依赖. 配置灵活:可方便.灵活的对每次所启动的任务,配置线程名.线程优先级等. ...
最新文章
- ERP实施需要一种态度
- 数学建模——智能优化之遗传算法详解Python代码
- R语言forestmodel包使用教程
- 在数据采集器中用TensorFlow进行实时机器学习
- 笔记:python3编写的仿hubot的聊天机器人Chattie
- Hystrix面试 - 基于 Hystrix 信号量机制实现资源隔离
- 移位运算符优先级很低
- 黑马程序员---交通灯管理系统
- 又一所小而精研究型大学!中科院与深圳共建,设AI等专业
- echarts3.0版本断点连线的处理
- jquery 动态添加,降低input表单的方法
- warning: left shift count = width of type
- vue.js动态组件:is特性
- 2019PMP项目管理考试报名时间取证流程-真题模拟题
- Excel连接Mysql数据库
- 省市县乡四级联动java代码,jQuery省市区街道四级联动代码
- 用python学概率与统计(第十二章)拟合度检验和独立性检验
- abaqus质量缩放系数取值_ABAQUS中的质量缩放
- 还儿童一个健康上网环境,正式开启我的路由器URL网址白名单之旅
- 第一模块-开发基础-第一章python语法
热门文章
- callable函数 stride的意义 Math.round(),Math.ceil(),Math.floor()用法
- 元数据交换绑定的秘密
- 下载并导出数据到execl中
- 设计模式学习笔记-观察者模式(转)
- 【分块答案】【最小割】bzoj1532 [POI2005]Kos-Dicing
- 非常棒的jQuery排版用插件
- java中ssh如何理解
- 从 2.4 到 2.6:Linux 内核可装载模块机制的改变对设备驱动的影响(一)
- windows mobile 鼠标等待
- mysql 原理 ~ 索引通说