• c++11 线程池学习笔记 (二) 线程池


    学习内容来自以下地址

    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 则有线程从队列中取出执行

    代码如下

     1 #pragma once
     2 
     3 #include <list>
     4 #include <mutex>
     5 #include <thread>
     6 #include <condition_variable>
     7 #include <iostream>
     8 
     9 using namespace std;
    10 
    11 template<typename T>
    12 class SyncQueue {
    13 public:
    14     SyncQueue(int maxSize):m_maxSize(maxSize),m_needStop(false){}
    15     void Put(const T& x) {
    16         Add(x);
    17     }
    18     void Put(T&& x) {
    19         Add(std::forward<T>(x));
    20     }
    21     void Take(std::list<T>& list) {
    22         std::unique_lock<std::mutex> locker(m_mutex);
    23         m_notEmpty.wait(locker, [this] {return m_needStop || NotEmpty(); });
    24         if (m_needStop)
    25             return;
    26         list = std::move(m_queue);
    27         m_notFull.notify_one();
    28     }
    29 
    30     void Take(T& t) {
    31         std::unique_lock<std::mutex> locker(m_mutex);
    32         m_notEmpty.wait(locker, [this] {return m_needStop || NotEmpty(); });
    33         if (m_needStop)
    34             return;
    35         t = m_queue.front();
    36         m_queue.pop_front();
    37         m_notFull.notify_one();
    38     }
    39 
    40     void Stop() {
    41         {
    42             std::lock_guard<std::mutex> locker(m_mutex);
    43             m_needStop = true;
    44         }
    45         m_notFull.notify_all();
    46         m_notEmpty.notify_all();
    47     }
    48 
    49     bool Empty() {
    50         std::lock_guard<std::mutex> locker(m_mutex);
    51         return m_queue.empty();
    52     }
    53 
    54     bool Full() {
    55         std::lock_guard<std::mutex> locker(m_mutex);
    56         return m_queue.size() == m_maxSize;
    57     }
    58 
    59     size_t Size() {
    60         std::lock_guard<std::mutex> locker(m_mutex);
    61         return m_queue.size();
    62     }
    63 
    64     int Count() {
    65         return m_queue.size();
    66     }
    67 private:
    68     bool NotFull()const {
    69         bool full = m_queue.size() >= m_maxSize;
    70         if (full)
    71             cout << "buffer area is full,wait..." << endl;
    72         return !full;
    73     }
    74     bool NotEmpty()const {
    75         bool empty = m_queue.empty();
    76         if (empty)
    77             cout << "buffer area is empty,wait... " << 
    78                 " threadID: " << this_thread::get_id() <<endl;
    79         return !empty;
    80     }
    81 
    82     template<typename F>
    83     void Add(F&& x) {
    84         std::unique_lock<std::mutex> locker(m_mutex);
    85         m_notFull.wait(locker, [this] {return m_needStop || NotFull(); });
    86         if (m_needStop)
    87             return;
    88         m_queue.push_back(std::forward<F>(x));
    89         m_notEmpty.notify_one();
    90     }
    91 private:
    92     std::list<T> m_queue;
    93     std::mutex m_mutex;
    94     std::condition_variable m_notEmpty;
    95     std::condition_variable m_notFull;
    96     int m_maxSize;
    97     bool m_needStop;
    98 };
    SyncQueue.h
      1 // ThreadPool.cpp: 定义控制台应用程序的入口点。
      2 //
      3 
      4 #include "stdafx.h"
      5 #include <list>
      6 #include <thread>
      7 #include <functional>
      8 #include <memory>
      9 #include <atomic>
     10 #include "SyncQueue.h"
     11 
     12 const int MaxTaskCount = 100;
     13 class ThreadPool {
     14     using Task = std::function<void()>;
     15 public:
     16     ThreadPool(int numThreads = std::thread::hardware_concurrency()) :m_queue(MaxTaskCount) {
     17         Start(numThreads);
     18     }
     19     ~ThreadPool(void) {
     20         Stop();
     21     }
     22     void Stop() {
     23         std::call_once(m_flag, [this] {StopThreadGroup(); });
     24     }
     25     void AddTask(Task&& task) {
     26         m_queue.Put(std::forward<Task>(task));
     27     }
     28     void AddTask(const Task& task) {
     29         m_queue.Put(task);
     30     }
     31 
     32     void Start(int numThreads) {
     33         m_running = true;
     34         for (int i = 0; i < numThreads; i++) {
     35             m_threadgroup.push_back(std::make_shared<std::thread>(&ThreadPool::RunInThread, this));
     36         }
     37     }
     38 private:
     39     void RunInThread() {
     40         while(m_running) {
     41             std::list<Task> list;
     42             m_queue.Take(list);
     43 
     44             for (auto& task : list) {
     45                 if (!m_running)
     46                     return;
     47                 task();
     48             }
     49         }
     50     }
     51 
     52     void StopThreadGroup() {
     53         m_queue.Stop();
     54         m_running = false;
     55         for (auto thread : m_threadgroup) {
     56             if (thread)
     57                 thread->join();
     58         }
     59         m_threadgroup.clear();
     60     }
     61     std::list<std::shared_ptr<std::thread>> m_threadgroup;
     62     SyncQueue<Task> m_queue;
     63     atomic_bool m_running;
     64     std::once_flag m_flag;
     65 };
     66 
     67 //=========================================================
     68 void TestThdPool() 
     69 {
     70     ThreadPool pool;
     71     pool.Start(2);
     72 
     73     std::thread thd1([&pool] {
     74         for (int i = 0; i < 10; i++) {
     75             auto thdId = this_thread::get_id();
     76             pool.AddTask([thdId] {
     77                 std::cout << "thread1 id : " << thdId << std::endl;
     78             });
     79         }
     80     });
     81 
     82     std::thread thd2([&pool] {
     83         for (int i = 0; i < 10; i++) {
     84             auto thdId = this_thread::get_id();
     85             pool.AddTask([thdId] {
     86                 std::cout << "thread2 id : " << thdId << std::endl;
     87             });
     88         }
     89     });
     90 
     91     this_thread::sleep_for(std::chrono::seconds(2));
     92     getchar();
     93     pool.Stop();
     94     thd1.join();
     95     thd2.join();
     96 }
     97 
     98 
     99 int main()
    100 {
    101     TestThdPool();
    102     return 0;
    103 }
    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

    作 者: itdef
    欢迎转帖 请保持文本完整并注明出处
    技术博客 http://www.cnblogs.com/itdef/
    B站算法视频题解
    https://space.bilibili.com/18508846
    qq 151435887
    gitee https://gitee.com/def/
    欢迎c c++ 算法爱好者 windows驱动爱好者 服务器程序员沟通交流
    如果觉得不错,欢迎点赞,你的鼓励就是我的动力
    阿里打赏 微信打赏
  • 相关阅读:
    python处理yml
    awk命令笔记
    微信小程序wxml的数据传给js 点击事件 js获取view中的内容
    微信小程序js 字符串截取
    微信小程序 wx:if 多条件判断
    微信小程序 --- toast消息提示框
    微信小程序 点击事件获取到的 event.currentTarget.dataset.id 是空的 解决办法
    微信小程序页面跳转传参数
    微信小程序开发框架
    微信小程序获取当前时间
  • 原文地址:https://www.cnblogs.com/itdef/p/8454491.html
Copyright © 2020-2023  润新知