(原创)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. Linux指令(压缩和解压类)

    gzip/gunzip 指令 gzip用于压缩文件,gunzip用于解压基本语法: gzip文件 (功能描述:压缩文件,只能将文件压缩为*.gz文件) gunzip文件.gz (功能描述:解压缩文件命 ...

  2. Httpd服务入门知识-Httpd服务常见配置案例之虚拟主机

    Httpd服务入门知识-Httpd服务常见配置案例之虚拟主机 作者:尹正杰 版权声明:原创作品,谢绝转载!否则将追究法律责任. 一.虚拟主机实现方案 1>.Apache httpd 有三种实现虚 ...

  3. (二)MongoDB基本概念

    (二)MongoDB基本概念 mongodb 2018年03月07日 08时43分53秒 mognoDB是一个面向文档的数据库,而不是关系型数据库,是不是用关系型数据库主要是为了获得更好的扩展性,还会 ...

  4. 性能测试基础---SQL基础

    ·数据库相关: ·范式:NF.关系型数据库的设计规则. 范式总计有6种: 1NF\2NF\3NF\BCNF\4NF\5NF ·范式的实现是从低到高的,比如说首先要实现的就是1NF,才能继续实现2NF, ...

  5. 2019年杭电多校第一场 1009题String(HDU6586+模拟+单调栈)

    题目链接 传送门 题意 给你一个字符串,要你构造一个长为\(k\)的子串使得每个字母出现的次数在\([L_i,R_i](0\leq i\leq26)\)间且字典序最小. 思路 做这种题目就是要保持思路 ...

  6. Appium中wait_activity的使用以及XPATH定位

    # -*- coding:utf-8 -*- from appium import webdriver from time import sleep desired_caps ={ 'platform ...

  7. 图论 - 二分图的判断(dfs染色法)

    二分图的判断(dfs染色法) 如何判断一个图是否为二分图 普通染色法模板 C++ 代码模板如下 思想:先将当前点染色,然后再将该点相连的结点进行染另外一种颜色 下面附上自己画的一张图假设我们从第一个点 ...

  8. Gym - 100962F: Frank Sinatra (树上莫队+bitset)

    题意:给定一棵树,带边权.然后Q次询问,每次给出(u,v),求这个路径上最小的未出现的边权. 思路:树上莫队,求mex可以用分块或者bitset,前者可能会快一点.   莫队过程:求出欧拉序,即记录d ...

  9. SpringBoot——探究HelloWorld【三】

    前言 前面我们写了helloworld的一个,这里我们对他进行分析 探究 那么下面就开始我们的探究之旅吧,首先从POM文件来,在POM文件中我们导入了项目所需要的依赖 POM文件 父项目 <pa ...

  10. 验证码破解 | Selenium模拟登录知乎

      import requests import re import execjs import time import hmac from hashlib import sha1 class Zhi ...