• 学习基于C++0x的threadpool简单实现


    学习了网上一片文章基于c++0x实现的threadpool,使用了很多新特性,学习了一番之后很有收获,加了注释希望可以帮助更多人。

    文章链接:https://cloud.tencent.com/developer/article/1478195

      1 #include <iostream>
      2 #include <map>
      3 #include <vector>
      4 #include <mutex>
      5 #include <future>
      6 #include <thread>
      7 #include <memory>
      8 #include <condition_variable>
      9 #include <functional>
     10 #include <queue>
     11 #include <stdexcept>
     12 
     13 class ThreadPool
     14 {
     15 public:
     16     ThreadPool(int size);
     17 
     18     template<class F, class... Args>
     19     auto enqueue(F&& f, Args... args) -> std::future<typename std::result_of<F(Args...)>::type>;
     20 
     21     ~ThreadPool();
     22 
     23 private:
     24     std::vector<std::thread> workers;
     25     std::queue<std::function<void()>> tasks;
     26 
     27     std::mutex _mutex;
     28     std::condition_variable _cond_var;
     29     bool stop;
     30 };
     31 
     32 ThreadPool::ThreadPool(int size):stop(false)
     33 {
     34     for(int i = 0; i < size; i++)
     35     {
     36         workers.emplace_back(
     37             [this] ()
     38             {
     39                 // 每个线程循环工作
     40                 for (;;)
     41                 {
     42                     std::function<void()> task;
     43                     {
     44                         std::unique_lock<std::mutex> lock(this->_mutex);
     45                         // 当队列为空 或者 没有停止pool时,会阻塞在这里,直到有任务
     46                         this->_cond_var.wait(lock, [this] ()
     47                         {
     48                             return this->stop || !this->tasks.empty();
     49                         });
     50                         // 对应析构中 notify_all 此时 stop 为 true
     51                         if (this->stop || this->tasks.empty())
     52                         {
     53                             return;
     54                         }
     55                         task = std::move(this->tasks.front());
     56                         this->tasks.pop();
     57                     }
     58                     task();
     59                 }
     60             }
     61         );
     62     }
     63 }
     64 
     65 /**
     66  * 这个看起来很复杂的定义是
     67  * 定义了函数 enqueue, 接收两个模板类型的参数, F类型 和 Args类型
     68  * F类型是函数,Args类型是参数列表
     69  * 返回值类型是 std::future<>, future返回的具体类型是 typename std::result_of<F(Args...)>::type , auto 是占位符
     70  * typename std::result_of<F(Args...)>::type 的意思是,方法 F(Args...) 的返回值的类型
     71  * 所以就是 std::future<F(Args...)> enqueue(F, Args...)
     72  * 可能出现的问题,就是塞入了太多的任务,导致队列内存爆掉
     73  */
     74 template<class F, class... Args>
     75 auto ThreadPool::enqueue(F&& f, Args... args) -> std::future<typename std::result_of<F(Args...)>::type>
     76 {
     77     // get return type
     78     using return_type = typename std::result_of<F(Args...)>::type;
     79     // create task
     80     // std::make_shared 产生了一个指针,指向了一个方法,方法是一个 std::packaged_task<> 包装的task,
     81     // 类型的签名是 return_type() 就是无参数,返回值类型 return_type
     82     auto task = std::make_shared<std::packaged_task<return_type()>>(
     83         std::bind(std::forward<F>(f), std::forward<Args>(args)...)
     84     );
     85     // get futre
     86     std::future<return_type> ret = task->get_future();
     87     {
     88         std::unique_lock<std::mutex> lock(_mutex);
     89         if (stop)
     90         {
     91             std::cout << "thread pool has stopped";
     92             throw std::runtime_error("pool stopped");
     93         }
     94         tasks.emplace([task] ()
     95         {
     96             (*task)();
     97         });
     98     }
     99     // notify_one 之后不一定能立刻执行,有空闲的线程才执行,没有就在队列里等待
    100     _cond_var.notify_one();
    101     return ret;
    102 }
    103 
    104 ThreadPool::~ThreadPool()
    105 {
    106     // 停止pool前要锁住
    107     {
    108         std::unique_lock<std::mutex> lock(_mutex);
    109         stop = true;
    110     }
    111     // 要通知多有的线程都停止工作,并join掉所有的线程
    112     _cond_var.notify_all();
    113     for (auto& item: workers)
    114     {
    115         item.join();
    116     }
    117 }
    118 
    119 int main()
    120 {
    121     ThreadPool _pool(4);
    122     /////////////////////////////////////////////////////////////
    123     auto result1 = _pool.enqueue([](int ans)
    124     {
    125         return ans;
    126     }, 100);
    127     std::cout << "ret:" << result1.get() << std::endl;
    128 
    129     /////////////////////////////////////////////////////////////
    130     auto result2 = _pool.enqueue([](char ans)
    131     {
    132         return ans;
    133     }, 'a');
    134     std::cout << "ret:" << result2.get() << std::endl;
    135 
    136     /////////////////////////////////////////////////////////////
    137     auto result3 = _pool.enqueue([](float ans)
    138     {
    139         return ans;
    140     }, 1.23);
    141     std::cout << "ret:" << result3.get() << std::endl;
    142 
    143     /////////////////////////////////////////////////////////////
    144     auto result4 = _pool.enqueue([](std::string ans)
    145     {
    146         return ans;
    147     }, "hello world");
    148     std::cout << "ret:" << result4.get() << std::endl;
    149 
    150     return 0;
    151 }
  • 相关阅读:
    NutUI 优秀案例
    前端进阶不可错过的 10 个 Github 仓库
    Oracle Database Appliance ODA开箱视频
    直面ODA(Oracle Database Appliance)RAC一体机
    Ask Maclean论坛礼仪需知及学习oracle的方法论
    My Oracle Support Metalink站点最近将放弃flash界面转而使用ADF HTML
    java设计模式之代理模式
    数学分析原理 定理 6.10
    halcon傅里叶变换
    halconget_system获取HALCON系统参数
  • 原文地址:https://www.cnblogs.com/warnet/p/13179400.html
Copyright © 2020-2023  润新知