#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. Chapter 2 Open Book——23

    Mike interrupted us then — he was planning an epic battle of the blizzard in the parking lot after s ...

  2. iOS开发运行时总是显示4s的尺寸

    今天新建了一个工程运行时,总是显示4s的尺寸,上面有一片黑,如下图所示: 解决方法:检查启动图片,没有包含6和6plus的启动图片,添加上启动图片时运行正常:

  3. HDU 4247 A Famous ICPC Team

    Problem Description Mr. B, Mr. G, Mr. M and their coach Professor S are planning their way to Warsaw ...

  4. Python处理Excel(转载)

    1. Python 操作 Excel 的函数库 我主要尝试了 3 种读写 Excel 的方法: 1> xlrd, xlwt, xlutils: 这三个库的好处是不需要其它支持,在任何操作系统上都 ...

  5. txt文件的读取

    两个函数:textread或importdata [textread函数] 格式:I=textread('文件名.txt','列',读取的行数,'headerlines',跳过的头行数);  返回值I ...

  6. Storm常见问题处理

    错误1:发布topologies到远程集群时,出现Nimbus host is not set异常.异常内容如下所示: [root@xop-dev-a bin]# ./storm jar /home/ ...

  7. MVC3+EF4.1学习系列(八)-----利用Repository and Unit of Work重构项目

    项目最基础的东西已经结束了,但是现在我们的项目还不健全  不利于测试 重复性代码多   层与层之间耦合性高  不利于扩展等问题.今天的这章 主要就是解决这些问题的.再解决这些问题时,自己也产生了很多疑 ...

  8. 图片上传预览 支持html5的浏览器

    <img src="" width="100px" height="100px"/> <input type=" ...

  9. Spring 中,对象销毁前执行某些处理的方法

    通过 @PreDestroy 和 bean 中配置 destroy-method 实现该功能 java 代码中: 1: public class TestClass { 2: private Sche ...

  10. 带宽 VS CDN (转载)

    并发的影响因素:带宽.web server(含php).static server.数据库 带宽价格: 静态IP企业宽带 5M 10M 50M 100M 200M 盛大云 华东双线 216/月 396 ...