#include <list>
#include <mutex>
#include <thread>
#include <condition_variable>
#include <iostream>
#include <functional>
#include <memory>
#include <atomic>
using namespace std; namespace itstation
{
template<typename T>
class SynaQueue
{
public:
SynaQueue(int maxSize)
:m_maxSize(maxSize), m_needStop(false)
{
} void Put(const T& x)
{
Add(x);
}
void Put(T&& x)
{
Add(forward<T>(x)); //完美转发,不改变参数的类型
}
void Take(list<T>& list)
{
std::unique_lock<mutex> locker(m_mutex);
// 判断式, 当都不满足条件时,条件变量会释放mutex, 并将线程置于waiting状态, 等待其他线程调用notify_one/all 将其唤醒。
// 当满足其中一个条件时继续执行, 将队列中的任务取出,唤醒等待添加任务的线程
// 当处于waiting状态的线程被唤醒时,先获取mutex,检查条件是否满足,满足-继续执行,否则释放mutex继续等待
m_notEmpty.wait(locker, [this]{return m_needStop || NotEmpty(); });
if (m_needStop)
return;
list = move(m_queue);
m_notFull.notify_one();
}
void Take(T& t)
{
unique_lock<mutex> locker(m_mutex); // 锁
m_notEmpty.wait(locker, [this]{return m_needStop || NotEmpty(); });
if (m_needStop)
return;
t = m_queue.front();
m_queue.pop_front();
m_notFull.notify_one();
}
void Stop()
{
{
lock_guard<mutex> locker(m_mutex);
m_needStop = true;
}
m_notFull.notify_all(); // 将所有等待的线程全部唤醒,被唤醒的进程检查m_needStop,为真,所有的线程退出执行
m_notEmpty.notify_all();
} private:
bool NotFull() const
{
bool full = m_queue.size() >= m_maxSize;
if (full)
cout << "缓冲区满了,需要等待。。。。" << endl;
return !full;
}
bool NotEmpty() const
{
bool empty = m_queue.empty();
if (empty)
cout << "缓冲区空了,需要等待,。。。异步层线程: " << this_thread::get_id() << endl;
return !empty;
} template<typename F>
void Add(F&& x)
{
unique_lock<mutex> locker(m_mutex); // 通过m_mutex获得写锁
m_notFull.wait(locker, [this]{return m_needStop || NotFull(); }); // 没有停止且满了,就释放m_mutex并waiting;有一个为真就继续执行
if (m_needStop)
return;
m_queue.push_back(forward<F>(x));
m_notEmpty.notify_one();
} private:
list<T> m_queue; //缓冲区
mutex m_mutex; // 互斥量
condition_variable m_notEmpty; // 条件变量
condition_variable m_notFull;
int m_maxSize; //同步队列最大的size
bool m_needStop; // 停止标识
}; const int MaxTaskCount = ;
class ThreadPool
{
public:
using Task = function < void() >;
ThreadPool(int numThread = thread::hardware_concurrency())
:m_queue(MaxTaskCount)
{
Start(numThread);
} virtual ~ThreadPool()
{
Stop();
} void Stop()
{
call_once(m_flag, [this]{StopThreadGroup(); });
} void AddTask(Task&& task)
{
m_queue.Put(forward<Task>(task));
} void AddTask(const Task& task)
{
m_queue.Put(task);
} private:
void Start(int numThreads)
{
m_running = true;
//创建线程组
for (int i = ; i < numThreads; i++)
{
m_threadgroup.emplace_back(make_shared<thread>(&ThreadPool::RunInThread, this));
}
} // 每个线程都执行这个函数
void RunInThread()
{
while (m_running)
{
//取任务分别执行
list<Task> list;
m_queue.Take(list);
for (auto& task : list)
{
if (!m_running)
return; task();
}
}
}
void StopThreadGroup()
{
m_queue.Stop(); // 同步队列中的线程停止
m_running = false; // 让内部线程跳出循环并推出
for (auto thread : m_threadgroup)
{
if (thread)
thread->join();
}
m_threadgroup.clear();
}
private:
list<shared_ptr<thread>> m_threadgroup; // 处理任务的线程组, 链表中存储着指向线程的共享指针
SynaQueue<Task> m_queue; //同步队列
atomic_bool m_running; // 是否停止的标识
once_flag m_flag;
};
} // namespace itstation #include <stdio.h>
#include <iostream>
#include "ObjectPool.h"
#include <list>
using namespace std;
using namespace itstation; void TestThreadPool()
{
ThreadPool pool();
thread thd1([&pool]{
for (int i = ; i < ; i++)
{
auto thrID = this_thread::get_id();
pool.AddTask([thrID, i]{cout << "同步层线程1的线程ID:" << thrID << " 这是任务 " << i << endl; this_thread::sleep_for(chrono::seconds()); });
}
}); thread thd2([&pool]{
for (int i = ; i < ; i++)
{
auto thrID = this_thread::get_id();
pool.AddTask([thrID, i]{cout << "同步层线程2的线程ID:" << thrID << " 这是任务 " << i << endl; this_thread::sleep_for(chrono::seconds()); });
}
}); this_thread::sleep_for(chrono::seconds());
pool.Stop();
thd1.join();
thd2.join();
}
int main()
{
TestThreadPool(); getchar();
return ;
}

C++11 半同步半异步线程池的实现的更多相关文章

  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. (原创)C++半同步半异步线程池2

    (原创)C++半同步半异步线程池 c++11 boost技术交流群:296561497,欢迎大家来交流技术. 线程池可以高效的处理任务,线程池中开启多个线程,等待同步队列中的任务到来,任务到来多个线程 ...

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

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

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

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

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

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

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

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

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

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

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

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

随机推荐

  1. LINQ 查询集合总的重复项

                      select new FMDS_FarmPlotNewInfo                   {                        FarmPlo ...

  2. Html网页的代码

    Html网页的代码 很全哦 1)贴图:<img src="图片地址"> 2)加入连接:<a href="所要连接的相关地址">写上你想写 ...

  3. MITMF

    一. 安装 项目地址:https://github.com/byt3bl33d3r/MITMf 需要自行手动安装python-nfqueue,pefile模块 sudo apt-get install ...

  4. [妙味JS基础]第三课:自定义属性、索引值

    知识点总结 自定义属性 元素.自定义属性 = 值: 比如: oDiv.abc = 100; =>abc为自定义属性 索引值 index  =>也是自定义属性 oDiv.index = '' ...

  5. 戏说HTML5(转)

    如果有非技术人员问你,HTML5是什么,你会怎么回答? 新的HTML规范... 给浏览器提供了牛逼能力,干以前不能干的事...(确切地说应该是给浏览器规定了许多新的接口标准,要求浏览器实现牛逼的功能. ...

  6. 1.javaOOP_Part1_抽象和封装

    javaOOP_Part1_抽象和封装 javaOOP_Part1_抽象和封装 1.1 面向对象 1.1.1 为什么使用面向对象 1.一切皆对象 2.现实世界就是"面向对象的" 3 ...

  7. 如何安装VM Tool软件包

    在linux下,我们想把原windows操作系统下的一些文件拷入到新linux系统中,在windows下对文件(夹)进行复制,在linux下无法进行粘贴,何故?这是因为新装的linux操作系统未安装V ...

  8. jQuery执行进度提示窗口的实现(progressbar)

    使用jQuery原生插件,先看效果: 主要是progressbar的更新进度以及“请稍等”后省略号.倒计时关闭的效果 如果执行单个任务的时间较长,会导致浏览器假死,一定要使用异步,代码结构要稍作调整. ...

  9. 基于多线程多用户的FTP服务器与客户端功能实现

    项目介绍: 用户加密认证 允许同时多用户登录 每个用户有自己的家目录 ,且只能访问自己的家目录 对用户进行磁盘配额,每个用户的可用空间不同 允许用户在ftp server上随意切换目录 允许用户查看当 ...

  10. Openjudge-计算概论(A)-晶晶赴约会

    描述 晶晶的朋友贝贝约晶晶下周一起去看展览,但晶晶每周的1.3.5有课必须上课,请帮晶晶判断她能否接受贝贝的邀请,如果能输出YES:如果不能则输出NO. 输入输入有一行,贝贝邀请晶晶去看展览的日期,用 ...