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

devtools/2025/2/5 17:43:35/

目录

实现一个无返回的线程池

完全代码实现

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/devtools/156339.html

相关文章

Linux系统编程:环境变量

目录 一.环境变量 1.1PATH引入 1.2HOME和SHELL 二.查看所有环境变量的方法 2.1命令行 2.2系统调用接口 2.2.1第三方变量 三.如何通过环境变量理解权限 四.命令行参数 4.1main函数的指令参数 4.2main函数的环境变量参数 4.3如何理解环境变量的全局性 4.4本地变量和环…

【大模型LLM面试合集】大语言模型架构_MHA_MQA_GQA

MHA_MQA_GQA 1.总结 在 MHA&#xff08;Multi Head Attention&#xff09; 中&#xff0c;每个头有自己单独的 key-value 对&#xff1b;标准的多头注意力机制&#xff0c;h个Query、Key 和 Value 矩阵。在 MQA&#xff08;Multi Query Attention&#xff09; 中只会有一组 k…

机器人抓取与操作概述(深蓝)——1

工业机器人&#xff1a;① “臂”的形态 ② “手”的形态 ③ 视觉&#xff0c;力和触觉 1 机器人的不同形态 “臂”的形态 “手”的形态 2 常见的操作任务 操作&#xff1a;插入、推和滑 抓取&#xff1a;两指&#xff08;平行夹爪&#xff09;抓取、灵巧手抓取 落地-产…

蓝桥杯算法笔记|差分学习

&#xff01;前情回顾 前缀和18437蓝桥账户中心 练习代码&#xff1a; #include <iostream> using namespace std; int main() {// 请在此输入您的代码int n,q;cin>>n>>q;int a[n];for(int i0;i<n;i){cin>>a[i];}int sum[n];sum[0]a[0];for(int …

ASP.NET Core Filter

目录 什么是Filter&#xff1f; Exception Filter 实现 注意 ActionFilter 注意 案例&#xff1a;自动启用事务的筛选器 事务的使用 TransactionScopeFilter的使用 什么是Filter&#xff1f; 切面编程机制&#xff0c;在ASP.NET Core特定的位置执行我们自定义的代码。…

DNS缓存详解(DNS Cache Detailed Explanation)

DNS缓存详解 清空DNS缓存可以让网页访问更快捷。本文将从什么是DNS缓存、为什么清空DNS缓存、如何清空DNS缓存、清空DNS缓存存在的问题四个方面详细阐述DNS缓存清空的相关知识。 一、什么是DNS缓存 1、DNS缓存的定义&#xff1a; DNS缓存是域名系统服务在遇到DNS查询时自动…

面试经典150题——图

文章目录 1、岛屿数量1.1 题目链接1.2 题目描述1.3 解题代码1.4 解题思路 2、被围绕的区域2.1 题目链接2.2 题目描述2.3 解题代码2.4 解题思路 3、克隆图3.1 题目链接3.2 题目描述3.3 解题代码3.4 解题思路 4、除法求值4.1 题目链接4.2 题目描述4.3 解题代码4.4 解题思路 5、课…

9.7 打造你的专属智能助手:基于 GPT Builder 定制化 ChatGPT 应用全指南

打造你的专属智能助手:基于 GPT Builder 定制化 ChatGPT 应用全指南 引言:让 AI 更懂你 在人工智能技术飞速发展的今天,ChatGPT 已成为提升效率和解放生产力的利器。然而,通用的 ChatGPT 可能无法完全满足个性化需求,这时候 GPT Builder 应运而生。它提供了一种直观、灵活…