(原创)C++半同步半异步线程池

c++11 boost技术交流群:296561497,欢迎大家来交流技术。

线程池可以高效的处理任务,线程池中开启多个线程,等待同步队列中的任务到来,任务到来多个线程会抢着执行任务,当到来的任务太多,达到上限时需要等待片刻,任务上限保证内存不会溢出。线程池的效率和cpu核数相关,多核的话效率更高,线程数一般取cpu数量+2比较合适,否则线程过多,线程切换频繁反而会导致效率降低。

线程池有两个活动过程:1.外面不停的往线程池添加任务;2.线程池内部不停的取任务执行。活动图如下:

线程池中的队列是用的上一篇博文中的同步队列。具体代码:

 
#include<vector>
#include<thread>
#include<functional>
#include<memory>
#include <atomic>
#include"SyncQueue.hpp" const int MaxTaskCount = 100;
class ThreadPool
{
public:
using Task = std::function<void()>;
ThreadPool(int numThreads = std::thread::hardware_concurrency()) : m_queue(MaxTaskCount)
{
Start(numThreads);
} ~ThreadPool(void)
{
//如果没有停止时则主动停止线程池
Stop();
} void Stop()
{
std::call_once(m_flag, [this]{StopThreadGroup(); }); //保证多线程情况下只调用一次StopThreadGroup
} void AddTask(Task&&task)
{
m_queue.Put(std::forward<Task>(task));
} void AddTask(const Task& task)
{
m_queue.Put(task);
} private:
void Start(int numThreads)
{
m_running = true;
//创建线程组
for (int i = 0; i <numThreads; ++i)
{
m_threadgroup.push_back(std::make_shared<std::thread>(&ThreadPool::RunInThread, this));
}
} void RunInThread()
{
while (m_running)
{
//取任务分别执行
std::list<Task> list;
m_queue.Take(list); for (auto& task : list)
{
if (!m_running)
return; task();
}
}
} void StopThreadGroup()
{
m_queue.Stop(); //让同步队列中的线程停止
m_running = false; //置为false,让内部线程跳出循环并退出 for (auto thread : m_threadgroup) //等待线程结束
{
if (thread)
thread->join();
}
m_threadgroup.clear();
} std::list<std::shared_ptr<std::thread>> m_threadgroup; //处理任务的线程组
SyncQueue<Task> m_queue; //同步队列
atomic_bool m_running; //是否停止的标志
std::once_flag m_flag;
};
 

上面的代码中用到了同步队列SyncQueue,它的实现在这里。测试代码如下:

 
void TestThdPool()
{
ThreadPool pool;bool runing = true; std::thread thd1([&pool,&runing]{
while(runing)
{
cout<<"produce "<<this_thread::get_id()<< endl; pool.AddTask([]{
std::cout <<"consume "<<this_thread::get_id()<< endl;
});
}
}); this_thread::sleep_for(std::chrono::seconds(10));
runing = false;
pool.Stop(); thd1.join();
getchar();
}
 

上面的测试代码中,thd1是生产者线程,线程池内部会不断消费生产者产生的任务。在需要的时候可以提前停止线程池,只要调用Stop函数就行了。

一点梦想:尽自己一份力,让c++的世界变得更美好!

(原创)C++半同步半异步线程池2的更多相关文章

  1. 使用C++11 开发一个半同步半异步线程池

    摘自:<深入应用C++11>第九章 实际中,主要有两种方法处理大量的并发任务,一种是一个请求由系统产生一个相应的处理请求的线程(一对一) 另外一种是系统预先生成一些用于处理请求的进程,当请 ...

  2. 使用C++11实现一个半同步半异步线程池

    前言 C++11之前我们使用线程需要系统提供API.posix线程库或者使用boost提供的线程库,C++11后就加入了跨平台的线程类std::thread,线程同步相关类std::mutex.std ...

  3. c++11 实现半同步半异步线程池

    感受: 随着深入学习,现代c++给我带来越来越多的惊喜- c++真的变强大了. 半同步半异步线程池: 事实上非常好理解.分为三层 同步层:通过IO复用或者其它多线程多进程等不断的将待处理事件加入到队列 ...

  4. 分布式缓存系统 Memcached 半同步/半异步模式

    在前面工作线程初始化的分析中讲到Memcached采用典型的Master_Worker模式,也即半同步/半异步的高效网络并发模式.其中主线程(异步线程)负责接收客户端连接,然后分发给工作线程,具体由工 ...

  5. 半同步半异步模式的实现 - MSMQ实现

    半同步半异步模式的实现 - MSMQ实现 所谓半同步半异步是指,在某个方法调用中,有些代码行是同步执行方式,有些代码行是异步执行方式,下面我们来举个例子,还是以经典的PlaceOrder来说,哈哈. ...

  6. 领导者/追随者(Leader/Followers)模型和半同步/半异步(half-sync/half-async)模型都是常用的客户-服务器编程模型

    领导者-追随者(Leader/Followers)模型的比喻 半同步/半异步模型和领导者/追随者模型的区别: 半同步/半异步模型拥有一个显式的待处理事件队列,而领导者-追随者模型没有一个显式的队列(很 ...

  7. SpringBoot使用异步线程池实现生产环境批量数据推送

    前言 SpringBoot使用异步线程池: 1.编写线程池配置类,自定义一个线程池: 2.定义一个异步服务: 3.使用@Async注解指向定义的线程池: 这里以我工作中使用过的一个案例来做描述,我所在 ...

  8. spring boot:使用async异步线程池发送注册邮件(spring boot 2.3.1)

    一,为什么要使用async异步线程池? 1,在生产环境中,有一些需要延时处理的业务场景: 例如:发送电子邮件, 给手机发短信验证码 大数据量的查询统计 远程抓取数据等 这些场景占用时间较长,而用户又没 ...

  9. Spring Boot系列二 Spring @Async异步线程池用法总结

    1. TaskExecutor Spring异步线程池的接口类,其实质是java.util.concurrent.Executor Spring 已经实现的异常线程池: 1. SimpleAsyncT ...

随机推荐

  1. jwt揭秘(含源码示例)

      JSON Web Tokens,是一种开发的行业标准 RFC 7519 ,用于安全的表示双方之间的声明.目前,jwt广泛应用在系统的用户认证方面,特别是现在前后端分离项目. 1. jwt认证流程 ...

  2. NLP文本分类方法汇总

    模型: FastText TextCNN TextRNN RCNN 分层注意网络(Hierarchical Attention Network) 具有注意的seq2seq模型(seq2seq with ...

  3. mmdetection安装教程

    如果官方教程不行再参考我的吧,我的环境如下: ubuntu cuda10 cudnn7.5 步骤: 1.使用conda创建一个虚拟环境 conda create -n mmdetection pyth ...

  4. 别名alias永久生效别名alias永久生效;虚拟机的NAT模式,进行静态IP配置,并A、B的实现免密访问

    别名alias永久生效 1.打开cd /etc/profile.d 目录 新建文件my_alias.sh 2.my_alias.sh里面添加 alias p=’poweroff -h’ alias r ...

  5. UiAutomatorViewer无法获取手机截图进行元素定位的解决办法

    问题描述 本来想使用UIAutomatorView定位app页面元素的,最开始我使用的是夜神模拟器,打开UIAutomatorView连接模拟器没有问题,但是后来我使用真机时发现无法连接到真机获取真机 ...

  6. selenium 2 设置浏览器安装路径

    selenium 2由于调用的是真实的浏览器,所以当你的浏览器不是安装在默认路径下,你就需要设定浏览器启动路径:若是默认路径,则程序中不需设定浏览器启动路径. 比如说用firefox进行测试 1. f ...

  7. LeetCode 1091. Shortest Path in Binary Matrix

    原题链接在这里:https://leetcode.com/problems/shortest-path-in-binary-matrix/ 题目: In an N by N square grid, ...

  8. 利用伪寄存器对MSVC++进行调试的介绍

    简介 让我们从我写这篇文章的原因开始.一天,一个同事让我帮他调试他遇到的问题.所以我看着他在输入代码,这时我注意到下面一行: int test = GetLastError(); 他这样做是因为他想知 ...

  9. 洛谷P1352 没有上司的舞会题解

    题目描述 某大学有N个职员,编号为1~N.他们之间有从属关系,也就是说他们的关系就像一棵以校长为根的树,父结点就是子结点的直接上司.现在有个周年庆宴会,宴会每邀请来一个职员都会增加一定的快乐指数Ri, ...

  10. js时间练习

    编写代码,将当前日期按"2017-12-27 11:11 星期三"格式输出 var t1 = new Date(); console.log(t1.toLocaleString() ...