#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. .net技术深入

    程序集(Assembly),可以看做是一堆相关类打一个包,相当于java中的jar包(*).打包的目的:程序中只引用必须的程序集,减小程序的尺寸:一些程序集内部的类不想让其他程序集调用. 我们调用的类 ...

  2. ValidationMessageFor验证

    一,在modle下的自己新建的PowerViewModel.cs下编辑错误显示 public class PowerViewModel    {        [Required( ErrorMess ...

  3. EMPTY isset unset var_dump 用法

    empty    判断一个变量是否为空,返回布尔值  isset  isset 判断一个值是否存在  unset取消变量设置, var_dump 打印变量并类型

  4. javase

    http://blog.csdn.net/itlwc/article/category/1572517 http://blog.csdn.net/itlwc

  5. 【Python&Sort】QuickSort

    Python版的快排,使用递归. 1.设置递归终止条件,当元素个数<1时 2.从列表中pop出一个元素pv 3.列表中的剩余值与pv进行对比,大的放入smaller列表,小的放入larger列表 ...

  6. 浙大pat1042题解

    1042. Shuffling Machine (20) 时间限制 400 ms 内存限制 32000 kB 代码长度限制 16000 B 判题程序 Standard 作者 CHEN, Yue Shu ...

  7. HDU 1509 Windows Message Queue(队列)

    题目链接 Problem Description Message queue is the basic fundamental of windows system. For each process, ...

  8. AWS ec2 vpn 搭建(20161014更新http://dl.fedoraproject.org/pub/epel/7/x86_64/e/epel-release-7-8.noarch.rpm)

    1.原来的SoftEther VPN Server在pc端不可用了,没找到原因,因此有搜索到了一个新方法,转自http://blog.csdn.net/henryng1994/article/deta ...

  9. Sitemesh 3

    Sitemesh 3 的使用及配置(收藏自:http://www.cnblogs.com/luotaoyeah/p/3776879.html) 1 . Sitemesh 3 简介 Sitemesh 是 ...

  10. zend guard Optimizer

    zend guard Optimizer PHP5.3+ URL:http://www.zend.com/en/products/guard/downloads Email:test001@test0 ...