高阶开发基础——快速入门C++并发编程6——大作业:实现一个超级迷你的线程池

news/2025/2/5 16:58:05/

目录

实现一个无返回的线程池

完全代码实现

Reference


实现一个无返回的线程池

实现一个简单的线程池非常简单,我们首先聊一聊线程池的定义:

线程池(Thread Pool) 是一种并发编程的设计模式,用于管理和复用多个线程,以提高程序的性能和资源利用率。它的核心思想是预先创建一组线程,并将任务分配给这些线程执行,而不是为每个任务单独创建和销毁线程。线程池广泛应用于需要处理大量短期任务的场景,例如 Web 服务器、数据库连接池、任务调度系统等。换而言之,线程池说白了就是一种饿汉思维——直接预先提供若干的线程,由线程池内部控制调度,确保我们可以只关心任务的提交以及完成。

我们下面要做的是设计一个任务是不返回的线程池。所以,我们约束我们的函数是:

using supportive_task_type = std::function<void()>;

下一步,就是构造我们的线程池的线程。注意的是——线程和任务是解耦合的,意味着我们需要一个中间函数解耦合任务派发。笔者决定,将任务派发分到一个私有函数完成:

    CCThreadPool(const int workers_num) {for(int i = 0; i < workers_num; i++){internal_threads.emplace_back([this](){__scheduled();});}}

上面这个代码很简单,就是将每一个线程都分配一个调度函数,这个调度函数来委派分发任务,办法说简单也很简单:

void __scheduled(){while(1){// sources protectionsstd::unique_lock<std::mutex> locker(internal_mutex);// waiting for the access of the task resourcescontrolling_cv.wait(locker, [this]{return thread_pool_status || !tasks_queue.empty();});// quit if requriedif(thread_pool_status && tasks_queue.empty()){return;}// 现在我们可以取到任务执行了supportive_task_type task(std::move(tasks_queue.front()));tasks_queue.pop();locker.unlock();task();}}

当析构的时候,我们也要通知所有线程的cv不要睡眠了,由于设置了thread_pool_status是true,直接线程跳出来结束全文。

    ~CCThreadPool(){thread_pool_status = true;controlling_cv.notify_all();for(auto& thread : internal_threads){thread.join();}}

完全代码实现

#include <condition_variable>
#include <functional>
#include <mutex>
#include <print>
#include <queue>
#include <thread>
#include <utility>
#include <vector>
​
class CCThreadPool {public:CCThreadPool()                          = delete;CCThreadPool(const CCThreadPool &)      = delete;CCThreadPool &operator=(CCThreadPool &) = delete;
​CCThreadPool(const int workers_num) {for(int i = 0; i < workers_num; i++){internal_threads.emplace_back([this](){__scheduled();});}}
​~CCThreadPool(){thread_pool_status = true;controlling_cv.notify_all();for(auto& thread : internal_threads){thread.join();}}
​template<typename F, typename... Args>void enTask(F&& f, Args&&... args){supportive_task_type task(std::bind(std::forward<F&&>(f), std::forward<Args&&>(args)...));{std::unique_lock<std::mutex> locker(internal_mutex);tasks_queue.emplace(std::move(task));}controlling_cv.notify_one();}
​private:void __scheduled(){while(1){std::unique_lock<std::mutex> locker(internal_mutex);controlling_cv.wait(locker, [this]{return thread_pool_status || !tasks_queue.empty();});// quitif(thread_pool_status && tasks_queue.empty()){return;}supportive_task_type task(std::move(tasks_queue.front()));tasks_queue.pop();locker.unlock();task();}}
​using supportive_task_type = std::function<void()>;std::vector<std::thread> internal_threads;std::queue<supportive_task_type> tasks_queue;std::mutex internal_mutex;std::condition_variable controlling_cv;bool thread_pool_status = false;
};
​
​
int main()
{std::println("Task start");CCThreadPool pool(4);for (int i = 0; i < 8; ++i) {pool.enTask([i] {std::println("Task {} is started at thread with id {}", i, std::this_thread::get_id());std::this_thread::sleep_for(std::chrono::seconds(1));std::println("Task {} is done", i);});}return 0;
}

Reference

8. C++11 跨平台线程池-See的编程日记 (seestudy.cn)


http://www.ppmy.cn/news/1569554.html

相关文章

jEasyUI 转换 HTML 表格为数据网格

jEasyUI 转换 HTML 表格为数据网格 引言 随着互联网技术的飞速发展,前端框架和库的应用越来越广泛。jEasyUI 是一款功能强大的 jQuery UI 扩展库,它提供了丰富的 UI 组件,其中数据网格(DataGrid)是 jEasyUI 中一个非常重要的组件。本文将详细介绍如何使用 jEasyUI 将一个…

ASP.NET Core与配置系统的集成

目录 配置系统 默认添加的配置提供者 加载命令行中的配置。 运行环境 读取方法 User Secrets 注意事项 Zack.AnyDBConfigProvider 案例 配置系统 默认添加的配置提供者 加载现有的IConfiguration。加载项目根目录下的appsettings.json。加载项目根目录下的appsettin…

对顾客行为的数据分析:融入2+1链动模式、AI智能名片与S2B2C商城小程序的新视角

摘要&#xff1a;随着互联网技术的飞速发展&#xff0c;企业与顾客之间的交互方式变得日益多样化&#xff0c;移动设备、社交媒体、门店、电子商务网站等交互点应运而生。这些交互点不仅为顾客提供了便捷的服务体验&#xff0c;同时也为企业积累了大量的顾客行为数据。本文旨在…

React第二十七章(Suspense)

Suspense Suspense 是一种异步渲染机制&#xff0c;其核心理念是在组件加载或数据获取过程中&#xff0c;先展示一个占位符&#xff08;loading state&#xff09;&#xff0c;从而实现更自然流畅的用户界面更新体验。 应用场景 异步组件加载&#xff1a;通过代码分包实现组件…

【Java-数据结构】Java 链表面试题下 “最后一公里”:解决复杂链表问题的致胜法宝

我的个人主页 我的专栏&#xff1a;Java-数据结构&#xff0c;希望能帮助到大家&#xff01;&#xff01;&#xff01;点赞❤ 收藏❤ 引言&#xff1a; Java链表&#xff0c;看似简单的链式结构&#xff0c;却蕴含着诸多有趣的特性与奥秘&#xff0c;等待我们去挖掘。它就像一…

RabbitMQ快速上手及入门

概念 概念&#xff1a; publisher&#xff1a;生产者&#xff0c;也就是发送消息的一方 consumer&#xff1a;消费者&#xff0c;也就是消费消息的一方 queue&#xff1a;队列&#xff0c;存储消息。生产者投递的消息会暂存在消息队列中&#xff0c;等待消费者处理 exchang…

一篇关于高等数理统计结合机器学习论文的撰写(如何撰写?)

前言 在大学或者研究生阶段&#xff0c;大家可能都会遇到一个问题就是&#xff0c;在上高等数理统计课程时&#xff0c;老师总会让同学们写一些大作业&#xff0c;比如论文什么的&#xff0c;接下来我会从计算机领域的角度&#xff0c;带领大家开启一篇从0到1的高等数理统计文…

DeSpread:Berachain 生态特点探讨与核心项目一览

撰文&#xff1a;DeSpread 引 言 Berachain 是一个 Layer 1 网路&#xff0c;以 PoL&#xff08;Proof of Liquidity&#xff09;共识机制为特色&#xff0c;使验证者、流动性提供者和协议的利益一致。目前&#xff0c;Berachain 正在进行第二个测试网路「bArtio Testnet」&a…