C++11 ThreadPool的应用

线程池的应用

代码结构
  • 任务队列
  • 线程池
  1. 工作线程
  2. 代码如下
#ifndef WBTHE_THREAD_POOL_H_
#define WBTHE_THREAD_POOL_H_

#include 
#include 
#include 
#include 
#include     // unique_ptr
#include 
#include 
#include 
#include 



class TaskQueue {
public:
  TaskQueue() = default;
  virtual ~TaskQueue() = default;

  virtual void enqueue(std::function fn) = 0;
    // 关闭
  virtual void shutdown() = 0;
    // 空闲状态
  virtual void on_idle(){};
};

class ThreadPool : public TaskQueue {
public:
  explicit ThreadPool(size_t n) : shutdown_(false) {
    while (n) {
      /**
       *  emplace_back() 在实现时,则是直接在容器尾部创建这个元素,省去了拷贝或移动元素的过程
       */
      threads_.emplace_back(worker(*this));
      n--;
    }
  }

  ThreadPool(const ThreadPool &) = delete;

  ~ThreadPool() override = default;

 /**
  * 传值方式下的std::function对象保存,使用转移操作std::move()
  */
  void enqueue(std::function fn) override {
    /**
     * std::unique_lock  锁锁管理模板类,通过对mutex的封装,
     * std::unique_lock对象以独占所有权的方式(unique owership)管理mutex对象的上锁和解锁操作,
     * 即在unique_lock对象的声明周期内,它所管理的锁对象会一直保持上锁状态;而unique_lock的生命周期结束之后,
     * 它所管理的锁对象会被解锁。unique_lock具有lock_guard的所有功能,
     * 而且更为灵活。虽然二者的对象都不能复制,但是unique_lock可以移动(movable),
     * 因此用unique_lock管理互斥对象,可以作为函数的返回值,也可以放到STL的容器中。
     *  https://blog.csdn.net/fengbingchun/article/details/78638138
     */
    std::unique_lock lock(mutex_);
    jobs_.push_back(std::move(fn));
    cond_.notify_one();
  }

  void shutdown() override {
    // Stop all worker threads...
    {
      std::unique_lock lock(mutex_);
      shutdown_ = true;
    }

    cond_.notify_all();

    //: - auto 是类型占位符,使用时必须初始化,用作类型的推导,在编译期间替换为变量的实际类型
    //: - auto 与 auto* 没有区别,但是auto声明引用类型时必须接&符号,int i = 10; auto &r = i;
    //: - auto 在同一行声明多个变量时,所有的类型都相同, auto只推导第一个类型。后面的同第一个类型相同
    //: - auto 不能做形参

    // 不加“&”的意思是取出array里面的每个对象,
    // 赋给t,t虽然被改变了,但数组里面的对象并没有变;加“&”表示t是数组里面 每个对象的别名
    // Join...
    for (auto &t : threads_) {
      t.join();
    }
  }

private:
  struct worker {
    explicit worker(ThreadPool &pool) : pool_(pool) {}

    void operator()() {
      for (;;) {
        std::function fn;
          //======独占互斥体锁 begin======
        {
          std::unique_lock lock(pool_.mutex_);
            /**
             [ ]  不捕获任何外部变量
             [& ]  以引用方式捕获所有变量,可以修改,但要当心引用无效
             */
          pool_.cond_.wait(
              lock, [&] { return !pool_.jobs_.empty() || pool_.shutdown_; });

          if (pool_.shutdown_ && pool_.jobs_.empty()) { break; }

          fn = pool_.jobs_.front();
          pool_.jobs_.pop_front();
        }
          //======end=====
        /**
         * 静态类型转换 转换为目标类型bool
         */
        assert(true == static_cast(fn));
        fn();
      }
    }

    ThreadPool &pool_;
  };
  friend struct worker;

  std::vector threads_;
  std::list< std::function > jobs_;

  bool shutdown_;

    /**
     用 std::unique_lock(通过 std::mutex) 来锁住当前线程。当前线程会一直被阻塞,
     直到另外一个线程在相同的 std::condition_variable 对象上调用了 notification 函数来唤醒当前线程。
     */
  std::condition_variable cond_;
  std::mutex mutex_;
};

#endif   // WBTHE_THREAD_POOL_H_

你可能感兴趣的:(C++11 ThreadPool的应用)