学习内容来自以下地址

http://www.cnblogs.com/qicosmos/p/4772486.html

github https://github.com/qicosmos/cosmos

有了任务队列 在程序运行之初 就预开启多个执行任务的线程 等待任务队列中传来的元素 对元素进行处理 执行完毕后 也不销毁线程 而是等待下个元素进行处理

使用std::list<std::shared_ptr<std::thread>> m_threadgroup; 变量记录线程指针 方便管理

测试例子中传递的元素类型定义为 td::function<void()> 即一个返回类型为void 无输入参数的函数

对应代码为using Task = std::function<void()>;

每当队列中添加该元素TASK 则有线程从队列中取出执行

代码如下

 #pragma once

 #include <list>
#include <mutex>
#include <thread>
#include <condition_variable>
#include <iostream> using namespace std; template<typename T>
class SyncQueue {
public:
SyncQueue(int maxSize):m_maxSize(maxSize),m_needStop(false){}
void Put(const T& x) {
Add(x);
}
void Put(T&& x) {
Add(std::forward<T>(x));
}
void Take(std::list<T>& list) {
std::unique_lock<std::mutex> locker(m_mutex);
m_notEmpty.wait(locker, [this] {return m_needStop || NotEmpty(); });
if (m_needStop)
return;
list = std::move(m_queue);
m_notFull.notify_one();
} void Take(T& t) {
std::unique_lock<std::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() {
{
std::lock_guard<std::mutex> locker(m_mutex);
m_needStop = true;
}
m_notFull.notify_all();
m_notEmpty.notify_all();
} bool Empty() {
std::lock_guard<std::mutex> locker(m_mutex);
return m_queue.empty();
} bool Full() {
std::lock_guard<std::mutex> locker(m_mutex);
return m_queue.size() == m_maxSize;
} size_t Size() {
std::lock_guard<std::mutex> locker(m_mutex);
return m_queue.size();
} int Count() {
return m_queue.size();
}
private:
bool NotFull()const {
bool full = m_queue.size() >= m_maxSize;
if (full)
cout << "buffer area is full,wait..." << endl;
return !full;
}
bool NotEmpty()const {
bool empty = m_queue.empty();
if (empty)
cout << "buffer area is empty,wait... " <<
" threadID: " << this_thread::get_id() <<endl;
return !empty;
} template<typename F>
void Add(F&& x) {
std::unique_lock<std::mutex> locker(m_mutex);
m_notFull.wait(locker, [this] {return m_needStop || NotFull(); });
if (m_needStop)
return;
m_queue.push_back(std::forward<F>(x));
m_notEmpty.notify_one();
}
private:
std::list<T> m_queue;
std::mutex m_mutex;
std::condition_variable m_notEmpty;
std::condition_variable m_notFull;
int m_maxSize;
bool m_needStop;
};

SyncQueue.h

 // ThreadPool.cpp: 定义控制台应用程序的入口点。
// #include "stdafx.h"
#include <list>
#include <thread>
#include <functional>
#include <memory>
#include <atomic>
#include "SyncQueue.h" const int MaxTaskCount = ;
class ThreadPool {
using Task = std::function<void()>;
public:
ThreadPool(int numThreads = std::thread::hardware_concurrency()) :m_queue(MaxTaskCount) {
Start(numThreads);
}
~ThreadPool(void) {
Stop();
}
void Stop() {
std::call_once(m_flag, [this] {StopThreadGroup(); });
}
void AddTask(Task&& task) {
m_queue.Put(std::forward<Task>(task));
}
void AddTask(const Task& task) {
m_queue.Put(task);
} void Start(int numThreads) {
m_running = true;
for (int i = ; i < numThreads; i++) {
m_threadgroup.push_back(std::make_shared<std::thread>(&ThreadPool::RunInThread, this));
}
}
private:
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;
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;
}; //=========================================================
void TestThdPool()
{
ThreadPool pool;
pool.Start(); std::thread thd1([&pool] {
for (int i = ; i < ; i++) {
auto thdId = this_thread::get_id();
pool.AddTask([thdId] {
std::cout << "thread1 id : " << thdId << std::endl;
});
}
}); std::thread thd2([&pool] {
for (int i = ; i < ; i++) {
auto thdId = this_thread::get_id();
pool.AddTask([thdId] {
std::cout << "thread2 id : " << thdId << std::endl;
});
}
}); this_thread::sleep_for(std::chrono::seconds());
getchar();
pool.Stop();
thd1.join();
thd2.join();
} int main()
{
TestThdPool();
return ;
}

ThreadPool.cpp

运行情况如下:

buffer area is empty,wait... threadID: 10244
buffer area is empty,wait... threadID: 8168
buffer area is empty,wait... threadID: 10136
buffer area is empty,wait... threadID: 5812
buffer area is empty,wait... threadID: 4064
buffer area is empty,wait... threadID: 7872
thread1 id : 9712buffer area is empty,wait... threadID:
8168
thread1 id : 9712
buffer area is empty,wait... threadID: 10244thread1 id : 9712

thread2 id : buffer area is empty,wait... threadID: thread2 id : 65206520
5812

thread2 id : thread1 id : thread2 id : 9712buffer area is empty,wait... threadID: thread2 id : 65206520
6520
thread2 id :
6520
thread2 id :
6520thread1 id :
40649712
thread2 id :
6520buffer area is empty,wait... threadID: thread2 id : 6520

thread1 id : 97125812

thread1 id : 9712buffer area is empty,wait... threadID: thread1 id : 10136

9712
buffer area is empty,wait... threadID: 7872thread1 id : 9712

thread2 id : 6520buffer area is empty,wait... threadID:
10244
thread1 id : 9712
buffer area is empty,wait... threadID: 8168

c++11 线程池学习笔记 (二) 线程池的更多相关文章

  1. JUC源码学习笔记5——线程池,FutureTask,Executor框架源码解析

    JUC源码学习笔记5--线程池,FutureTask,Executor框架源码解析 源码基于JDK8 参考了美团技术博客 https://tech.meituan.com/2020/04/02/jav ...

  2. 操作系统学习笔记----进程/线程模型----Coursera课程笔记

    操作系统学习笔记----进程/线程模型----Coursera课程笔记 进程/线程模型 0. 概述 0.1 进程模型 多道程序设计 进程的概念.进程控制块 进程状态及转换.进程队列 进程控制----进 ...

  3. java学习笔记15--多线程编程基础2

    本文地址:http://www.cnblogs.com/archimedes/p/java-study-note15.html,转载请注明源地址. 线程的生命周期 1.线程的生命周期 线程从产生到消亡 ...

  4. JMX学习笔记(二)-Notification

    Notification通知,也可理解为消息,有通知,必然有发送通知的广播,JMX这里采用了一种订阅的方式,类似于观察者模式,注册一个观察者到广播里,当有通知时,广播通过调用观察者,逐一通知. 这里写 ...

  5. Linux内核学习笔记二——进程

    Linux内核学习笔记二——进程   一 进程与线程 进程就是处于执行期的程序,包含了独立地址空间,多个执行线程等资源. 线程是进程中活动的对象,每个线程都拥有独立的程序计数器.进程栈和一组进程寄存器 ...

  6. muduo学习笔记(二)Reactor关键结构

    目录 muduo学习笔记(二)Reactor关键结构 Reactor简述 什么是Reactor Reactor模型的优缺点 poll简述 poll使用样例 muduo Reactor关键结构 Chan ...

  7. python3.4学习笔记(二) 类型判断,异常处理,终止程序

    python3.4学习笔记(二) 类型判断,异常处理,终止程序,实例代码: #idle中按F5可以运行代码 #引入外部模块 import xxx #random模块,randint(开始数,结束数) ...

  8. JDBC学习笔记二

    JDBC学习笔记二 4.execute()方法执行SQL语句 execute几乎可以执行任何SQL语句,当execute执行过SQL语句之后会返回一个布尔类型的值,代表是否返回了ResultSet对象 ...

  9. Java IO学习笔记二

    Java IO学习笔记二 流的概念 在程序中所有的数据都是以流的方式进行传输或保存的,程序需要数据的时候要使用输入流读取数据,而当程序需要将一些数据保存起来的时候,就要使用输出流完成. 程序中的输入输 ...

随机推荐

  1. Python模块hashlib

    Python的hashlib提供了常见的摘要算法,如MD5,SHA1等等. 什么是摘要算法呢?摘要算法又称哈希算法.散列算法.它通过一个函数,把任意长度的数据转换为一个长度固定的数据串(通常用16进制 ...

  2. xterm下字体设置

    code ~/.Xdefaults xterm*locale: true xterm.utf8: true xterm*utf8Title: true ! 滚动条 !XTerm*scrollBar: ...

  3. 浏览器调试动态js脚本

    前两天拉取公司前端代码修改,发现在开发者工具的sources选项里边,居然没有列出来我要调试的js脚本,后来观察了一下,脚本是动态在页面里引入的,可能是因为这样所以不显示出来,但是如果不能断点调试,只 ...

  4. nginx配置分发Tomcat服务,负载均衡

    文章版权由作者李晓晖和博客园共有,若转载请于明显处标明出处:http://www.cnblogs.com/naaoveGIS/ 1.背景 项目中瓦片资源越来越多,如果提高瓦片的访问效率是一个需要解决的 ...

  5. cookies的常见方式

    cookie有如下特点 保存在客户端,一般由浏览器负责存储在本地. 通常是加密存储的,不过由于存储在本地,很难保证数据不被非法访问,并不怎么安全,所以cookies中不宜保存敏感信息,如密码等. 哪些 ...

  6. 多线程之sleep和wait的区别

    它们最大本质的区别是:sleep()不释放同步锁,wait()释放同步锁. 还有用法的上的不同是:sleep(milliseconds)可以用时间指定来使他自动醒过来,如果时间不到你只能调用inter ...

  7. 图灵一代接入V1

    现在官方没有一代接入了,但是还是可用,留个方法 $.ajax({ type:"post", url:"http://www.tuling123.com/openapi/a ...

  8. java细节知识

    代码优化细节 (1)尽量指定类.方法的final修饰符 带有final修饰符的类是不可派生的.在Java核心API中,有许多应用final的例子,例如java.lang.String,整个类都是fin ...

  9. Android Jetpack 概述

    Android Jetpack Overview Android Jetpack Jetpack is a set of libraries, tools and architectural guid ...

  10. 04 Python数据类型

    Python 数据型1. int: 1,2,3 ....2. bool: True False3. str: 存贮少量数据 'asjkdh','工查'4. list: 列表,存贮大量数据 [1,2,3 ...