• C++项目实战--线程池代码讲解


    先上代码:

    1. #ifndef THREADPOOL_H
    2. #define THREADPOOL_H
    3. #include
    4. #include
    5. #include
    6. #include
    7. #include
    8. class ThreadPool {
    9. public:
    10. explicit ThreadPool(size_t threadCount = 8): pool_(std::make_shared()) {
    11. assert(threadCount > 0); //断言
    12. for(size_t i = 0; i < threadCount; i++) { //创建 threadCount个工作线程
    13. std::thread([pool = pool_] { //创建线程 将pool_ 赋值给 pool
    14. std::unique_lock locker(pool->mtx); //创建一个锁
    15. //工作线程的逻辑
    16. while(true) { //不断的去向工作队列请求
    17. if(!pool->tasks.empty()) { //如果工作队列不为空
    18. auto task = std::move(pool->tasks.front());//获取一个任务
    19. pool->tasks.pop(); //队列弹出已经被获取的任务
    20. locker.unlock(); //解锁
    21. task(); //处理任务
    22. locker.lock(); //上锁
    23. }
    24. else if(pool->isClosed) break; //如果工作队列为空,并且池子已经关闭,退出
    25. else pool->cond.wait(locker); //如果工作队列为空并且线程池没有关闭,则设置该工作线程阻塞等待 条件变量-1
    26. }
    27. }).detach(); //设置线程分离
    28. }
    29. }
    30. ThreadPool() = default; //采用默认的构造函数
    31. ThreadPool(ThreadPool&&) = default; //采用默认的拷贝构造函数
    32. ~ThreadPool() {
    33. if(static_cast<bool>(pool_)) {
    34. {
    35. std::lock_guard locker(pool_->mtx); //创建一个锁
    36. pool_->isClosed = true; //关闭线程池
    37. }
    38. pool_->cond.notify_all(); //唤醒线程池中所以的线程,线程最终就会进入 else if(pool->isClosed) break; 逻辑,最后退出
    39. }
    40. }
    41. template<class F>
    42. void AddTask(F&& task) { //向线程池中添加任务
    43. {
    44. std::lock_guard locker(pool_->mtx); //创建一个锁
    45. pool_->tasks.emplace(std::forward(task)); //向工作队列中插入一个任务
    46. }
    47. pool_->cond.notify_one(); //唤醒一个线程 条件变量+1
    48. }
    49. private:
    50. struct Pool {
    51. std::mutex mtx; //互斥锁
    52. std::condition_variable cond; //条件变量
    53. bool isClosed; //线程池是否关闭
    54. std::queuevoid()>> tasks; //工作队列
    55. };
    56. std::shared_ptr pool_; //定义一个 Pool指针
    57. };
    58. #endif //THREADPOOL_H

    这段代码是通过c++14写的,我们主要看逻辑关系和实现的原理。

    一般线程池的实现的模型:消费者生产者

    既然是生产者消费者模型,就设计到了线程同步的问题。。。。

    线程同步问题:互斥量,条件变量

    我们把代码分为三个部分来看:

    这一部分是线程池所需要的一些条件

    将互斥锁、条件变量、线程池是否关闭的状态、工作队列封装到一起,然后通过智能指针(共享的)来操作管理这些条件

     向生产者向工作队列中添加任务(主线程去完成),并设置唤醒

    explicit:防止构造函数出现隐式转换。比如 A  a = 8,这样是不允许的

    通过while不断让工作线程的请求工作队列,如果工作队列不为空,则获取一个任务并处理。如果工作队列为空并且线程池已经关闭,则直接跳出。如果工作队列不为空并且线程池没有关闭,则阻塞等待被唤醒。

    使用线程池可以减少线程的销毁,而且如果不使用线程池的话,来一个客户端就创建一个线程。比如有1000,这样线程的创建、线程之间的调度也会耗费很多的系统资源,所以采用线程池使程序的效率更高。 线程池就是项目启动的时候,就先把线程池准备好。

     

  • 相关阅读:
    linux系统安装jdk
    uniapp 跳转页面 和 记录一些其他的坑
    java-net-php-python-jsp社会公共常识科普网的设计与实现计算机毕业设计程序
    盲盒小程序 跨平台兼容性测试策略:打造无缝体验
    Flink 监控检查点 Checkpoint
    安装ESXi 虚拟机
    新库上线 | CnOpenData中国各地区方言信息数据
    C++算法前缀和的应用:得分最高的最小轮调的原理、源码及测试用例
    “点工”的觉悟,5年时间从7K到25K的转变,我的测试道路历程
    input文本去除括号和标点符号回车
  • 原文地址:https://blog.csdn.net/weixin_46120107/article/details/126652875