c++线程池

cpp 复制代码
// 引入必要的头文件
#include <iostream>
#include <vector>
#include <queue>
#include <thread>
#include <mutex>
#include <condition_variable>
#include <functional>
#include <atomic>
#include <string>
using namespace std;

// 定义一个任务类,封装了要执行的函数和参数
class Task {
public:
    // 使用可变参数模板和完美转发构造函数
    template<typename F, typename... Args>
    Task(F&& f, Args&&... args) {
        // 使用lambda表达式和std::bind将函数和参数绑定在一起
        func = std::bind(std::forward<F>(f), std::forward<Args>(args)...);
    }

    // 执行任务
    void run() {
        func();
    }

private:
    // 使用std::function存储可调用对象
    std::function<void()> func;
};

// 定义一个线程池类,管理一组线程和一个任务队列
class ThreadPool {
public:
    // 构造函数,初始化线程池
    ThreadPool(size_t size) : stop(false) {
        // 根据指定的大小创建线程
        for (size_t i = 0; i < size; i++) {
            // 使用lambda表达式作为线程函数
            workers.emplace_back([this] {
                // 循环执行任务,直到线程池停止
                while (true) {
                    // 定义一个任务指针
                    Task* task;
                    // 使用互斥锁保护任务队列的访问
                    {
                        std::unique_lock<std::mutex> lock(this->queue_mutex);
                        // 使用条件变量等待任务的到来,或者线程池的停止
                        this->condition.wait(lock, [this] {
                            return this->stop || !this->tasks.empty();
                            });
                        // 如果线程池停止,并且任务队列为空,就退出循环
                        if (this->stop && this->tasks.empty()) {
                            return;
                        }
                        // 从任务队列中取出一个任务
                        task = this->tasks.front();
                        this->tasks.pop();
                    }
                    // 执行任务
                    task->run();
                    // 释放任务的内存
                    delete task;
                }
                });
        }
    }

    // 析构函数,销毁线程池
    ~ThreadPool() {
        // 使用互斥锁保护stop变量的访问
        {
            std::unique_lock<std::mutex> lock(queue_mutex);
            // 设置stop为true,表示线程池要停止
            stop = true;
        }
        // 通知所有等待的线程
        condition.notify_all();
        // 等待所有线程结束
        for (std::thread& worker : workers) {
            worker.join();
        }
    }

    // 向任务队列中添加一个任务
    template<typename F, typename... Args>
    void enqueue(F&& f, Args&&... args) {
        // 创建一个任务对象,使用new分配内存
        Task* task = new Task(std::forward<F>(f), std::forward<Args>(args)...);
        // 使用互斥锁保护任务队列的访问
        {
            std::unique_lock<std::mutex> lock(queue_mutex);
            // 将任务添加到队列中
            tasks.push(task);
        }
        // 通知一个等待的线程
        condition.notify_one();
    }

private:
    // 一组工作线程
    std::vector<std::thread> workers;
    // 一个任务队列
    std::queue<Task*> tasks;
    // 一个互斥锁,用于同步对任务队列的访问
    std::mutex queue_mutex;
    // 一个条件变量,用于等待和通知任务的到来
    std::condition_variable condition;
    // 一个原子布尔变量,用于表示线程池是否要停止
    std::atomic<bool> stop;
};


// 定义一个简单的函数,用于打印一些信息
void print_info(std::thread::id id, const std::string& msg) {
    // 使用互斥锁保护标准输出的访问
    static std::mutex cout_mutex;
    std::unique_lock<std::mutex> lock(cout_mutex);
    // 打印线程的id和信息
    std::cout << "Thread " << id << ": " << msg << std::endl;
}

// 定义一个main函数,用于测试线程池
int main() {
    // 创建一个大小为4的线程池
    ThreadPool pool(4);
    // 向线程池中添加10个任务
    for (int i = 0; i < 10; i++) {
        // 使用lambda表达式作为任务的函数
        pool.enqueue([i] {
              std::thread::id id = std::this_thread::get_id();
            // 调用print_info函数,传递当前线程的id和一个信息
            print_info(id, "Hello from task " + std::to_string(i));
            });
    }
    // 等待线程池的析构,自动结束所有线程
    return 0;
}
相关推荐
CoderCodingNo7 分钟前
【CSP】CSP-XL 2025辽宁复赛真题-第四题, 购物(buy)
算法
CDwenhuohuo23 分钟前
uniapp去掉手机状态栏 全屏展示
开发语言·javascript·uni-app
mjhcsp29 分钟前
P14795 [JOI 2026 二次预选] 分班 / Class Division
数据结构·c++·算法
闻缺陷则喜何志丹30 分钟前
【计算几何 最短路 动态规划】P1354 房间最短路问题
数学·算法·动态规划·最短路·计算几何·洛谷
别多香了38 分钟前
Python 基础--循环判断&字符串
开发语言·python
girl-07261 小时前
2025.12.29实验题目分析总结
数据结构·算法
点云SLAM1 小时前
Truncated Least Squares(TLS 截断最小二乘)算法原理
算法·slam·位姿估计·数值优化·点云配准·非凸全局优化·截断最小二乘法
早点睡觉好了1 小时前
JAVA中基本类型和包装类型的区别
java·开发语言
sin_hielo1 小时前
leetcode 840
数据结构·算法·leetcode
feifeigo1231 小时前
基于MATLAB的木材图像去噪算法实现
算法·计算机视觉·matlab