最近在看面经的过程中遇到一个问题  线程池的实现   我想了想  完全不会啊   于是就开始了我的线程池学习之路

在网上仔细研究了一下那个100行的C++线程池代码(那个作者在花式秀C++11),不过有一说一  他写的确实好。

 

先上代码

  1 #include <vector>
  2 #include <queue>
  3 #include <memory>
  4 #include <thread>
  5 #include <mutex>
  6 #include <condition_variable>
  7 #include <future>
  8 #include <functional>
  9 #include <stdexcept>
 10 #include <iostream>
 11 
 12 using namespace std;
 13 
 14 class ThreadPool {
 15 public:
 16     ThreadPool(size_t);    //构造函数,size_t n 表示连接数
 17 
 18     template<class F, class... Args>
 19     auto enqueue(F &&f, Args &&... args)   //任务管道函数
 20     -> std::future<typename std::result_of<F(Args...)>::type>;  // 利用尾置限定符  std future用来获取异步任务的结果
 21 
 22     ~ThreadPool();
 23 
 24 private:
 25     // need to keep track of threads so we can join them
 26     std::vector<std::thread> workers;   //追踪线程
 27     // the task queue
 28     std::queue<std::function<void()> > tasks;    //任务队列,用于存放没有处理的任务。提供缓冲机制
 29 
 30     // synchronization  同步?
 31     std::mutex queue_mutex;   //互斥锁
 32     std::condition_variable condition;   //条件变量?
 33     bool stop;
 34 };
 35 
 36 // the constructor just launches some amount of workers
 37 inline ThreadPool::ThreadPool(size_t threads) : stop(false) {
 38     for (size_t i = 0; i < threads; ++i)
 39         workers.emplace_back(     //以下为构造一个任务,即构造一个线程
 40                 [this] {
 41                     for (;;) {
 42                         std::function<void()> task;   //线程中的函数对象
 43                         {//大括号作用:临时变量的生存期,即控制lock的时间
 44                             std::unique_lock<std::mutex> lock(this->queue_mutex);
 45                             this->condition.wait(lock,
 46                                                  [this] {
 47                                                      return this->stop || !this->tasks.empty();
 48                                                  }); //当stop==false&&tasks.empty(),该线程被阻塞 !this->stop&&this->tasks.empty()
 49                             if (this->stop && this->tasks.empty()) return;
 50                             task = std::move(this->tasks.front());
 51                             this->tasks.pop();
 52                         }
 53                         task(); //调用函数,运行函数
 54                     }
 55                 }
 56         );
 57 }
 58 
 59 // add new work item to the pool
 60 template<class F, class... Args>
 61 auto ThreadPool::enqueue(F &&f, Args &&... args)  //&& 引用限定符,参数的右值引用,  此处表示参数传入一个函数
 62 -> std::future<typename std::result_of<F(Args...)>::type> {
 63     using return_type = typename std::result_of<F(Args...)>::type;
 64     //packaged_task是对任务的一个抽象,我们可以给其传递一个函数来完成其构造。之后将任务投递给任何线程去完成,通过
 65 //packaged_task.get_future()方法获取的future来获取任务完成后的产出值
 66     auto task = std::make_shared<std::packaged_task<return_type()> >(  //指向F函数的智能指针
 67             std::bind(std::forward<F>(f), std::forward<Args>(args)...)  //传递函数进行构造
 68     );
 69     //future为期望,get_future获取任务完成后的产出值
 70     std::future<return_type> res = task->get_future();   //获取future对象,如果task的状态不为ready,会阻塞当前调用者
 71     {
 72         std::unique_lock<std::mutex> lock(queue_mutex);  //保持互斥性,避免多个线程同时运行一个任务
 73         // don't allow enqueueing after stopping the pool
 74         if (stop) throw std::runtime_error("enqueue on stopped ThreadPool");
 75         tasks.emplace([task]() { (*task)(); });  //将task投递给线程去完成,vector尾部压入
 76     }
 77     condition.notify_one();  //选择一个wait状态的线程进行唤醒,并使他获得对象上的锁来完成任务(即其他线程无法访问对象)
 78     return res;
 79 }//notify_one不能保证获得锁的线程真正需要锁,并且因此可能产生死锁
 80 
 81 // the destructor joins all threads
 82 inline ThreadPool::~ThreadPool() {
 83     {
 84         std::unique_lock<std::mutex> lock(queue_mutex);
 85         stop = true;
 86     }
 87     condition.notify_all();  //通知所有wait状态的线程竞争对象的控制权,唤醒所有线程执行
 88     for (std::thread &worker: workers)
 89         worker.join(); //因为线程都开始竞争了,所以一定会执行完,join可等待线程执行完  销毁进程池里面的进程
 90 }
 91 
 92 char the_task(int i) {
 93     std::cout << "worker thread ID:" << std::this_thread::get_id() << std::endl;
 94     return 'a' + i;
 95 }
 96 
 97 
 98 int main() {
 99     ThreadPool pool(4);
100     std::vector<std::future<char> > results;
101     for (int i = 0; i < 8; ++i) results.emplace_back(pool.enqueue(the_task, i));
102     for (auto &&result: results)    //通过future.get()获取返回值
103         std::cout << result.get() << ' ';
104     std::cout << std::endl;
105 
106     return 0;
107 }
View Code

相关文章:

  • 2021-07-08
  • 2021-09-07
  • 2021-09-15
  • 2021-10-19
  • 2022-01-31
  • 2021-11-10
  • 2022-12-23
猜你喜欢
  • 2021-07-16
  • 2021-12-06
  • 2022-12-23
  • 2022-12-23
  • 2022-12-23
  • 2022-02-22
  • 2021-11-22
相关资源
相似解决方案