当前位置: 首页 > article >正文

C++线程池的使用

在 C++ 中,线程池是一种用于管理和复用多个线程的设计模式,可以有效地提高程序的性能,特别是在需要频繁创建和销毁线程时。C++11 引入了许多多线程相关的库,使得实现线程池变得相对简单。

一、线程池的定义

#include <iostream>
#include <thread>
#include <vector>
#include <queue>
#include <functional>
#include <condition_variable>
#include <future>
#include <atomic>

class ThreadPool {
public:
    ThreadPool(size_t numThreads);
    ~ThreadPool();

    template<class F>
    auto enqueue(F&& f) -> std::future<typename std::result_of<F()>::type>;

private:
    std::vector<std::thread> workers; // 工作线程
    std::queue<std::function<void()>> tasks; // 任务队列

    std::mutex queueMutex; // 保护任务队列的互斥锁
    std::condition_variable condition; // 条件变量
    bool stop; // 停止标志
};

// 构造函数
ThreadPool::ThreadPool(size_t numThreads) : stop(false) {
    for (size_t i = 0; i < numThreads; ++i) {
        workers.emplace_back([this] {
            for (;;) {
                std::function<void()> task;
                {
                    std::unique_lock<std::mutex> lock(this->queueMutex);
                    this->condition.wait(lock, [this] { return this->stop || !this->tasks.empty(); });
                    if (this->stop && this->tasks.empty()) {
                        return; // 如果停止并且任务队列为空,退出线程
                    }
                    task = std::move(this->tasks.front());
                    this->tasks.pop();
                }
                task(); // 执行任务
            }
        });
    }
}

// 析构函数
ThreadPool::~ThreadPool() {
    {
        std::unique_lock<std::mutex> lock(queueMutex);
        stop = true; // 设置停止标志
    }
    condition.notify_all(); // 唤醒所有线程
    for (std::thread &worker : workers) {
        worker.join(); // 等待所有线程结束
    }
}

// 向线程池添加任务
template<class F>
auto ThreadPool::enqueue(F&& f) -> std::future<typename std::result_of<F()>::type> {
    using return_type = typename std::result_of<F()>::type;

    auto task = std::make_shared<std::packaged_task<return_type()>>(std::forward<F>(f));
    std::future<return_type> res = task->get_future();
    {
        std::unique_lock<std::mutex> lock(queueMutex);
        // 不允许在停止状态下添加任务
        if (stop) {
            throw std::runtime_error("enqueue on stopped ThreadPool");
        }
        tasks.emplace([task]() { (*task)(); }); // 将任务添加到队列
    }
    condition.notify_one(); // 唤醒一个等待线程
    return res; // 返回 future
}

二、使用线程池

#include <iostream>
#include <chrono>
#include "ThreadPool.h" // 假设 ThreadPool 类在这个头文件中定义

int main() {
    ThreadPool pool(4); // 创建一个线程池,包含 4 个线程

    // 提交一些任务
    std::vector<std::future<void>> futures;
    for (int i = 0; i < 10; ++i) {
        futures.emplace_back(pool.enqueue([i] {
            std::cout << "Task " << i << " is running on thread " << std::this_thread::get_id() << std::endl;
            std::this_thread::sleep_for(std::chrono::seconds(1)); // 模拟任务执行
        }));
    }

    // 等待所有任务完成
    for (auto& future : futures) {
        future.get(); // 获取结果,等待任务完成
    }

    return 0;
}

三、说明

  1. ThreadPool 类:

    • 该类包含一个线程池的实现,允许用户提交任务并在后台线程中执行。
    • 使用 std::queue 存储任务,使用 std::mutex 和 std::condition_variable 进行线程同步。
    • 提供 enqueue 方法来添加任务,并返回一个 std::future 对象,以便用户可以等待任务完成并获取结果。
  2. 使用示例:

    • 创建一个包含 4 个线程的线程池。
    • 使用 enqueue 方法提交 10 个任务,每个任务在不同的线程中运行,并输出当前线程 ID。
    • 使用 future.get() 等待所有任务完成。

四、总结

这个简单的线程池实现可以处理并发任务,减少线程创建和销毁的开销。可以根据需要扩展功能,例如添加任务优先级、动态调整线程数等。使用线程池可以有效提高程序的性能,尤其是在需要处理大量短时间运行的任务时


http://www.kler.cn/a/460893.html

相关文章:

  • AWS K8s 部署架构
  • C# 标准数字格式字符串
  • log4j2的Strategy、log4j2的DefaultRolloverStrategy、删除过期文件
  • 2025-1-2-sklearn学习(30)模型选择与评估-验证曲线: 绘制分数以评估模型 真珠帘卷玉楼空,天淡银河垂地。
  • 从单点 Redis 到 1 主 2 从 3 哨兵的架构演进之路
  • 电脑主机后置音频插孔无声?还得Realtek高清晰音频管理器调教
  • 智能商业分析 Quick BI
  • Spring Security 3.0.2.3版本
  • 为什么需要设置 `NCCL_P2P_DISABLE=1` 和 `NCCL_IB_DISABLE=1`?
  • 4G报警器WT2003H-16S低功耗语音芯片方案开发-实时音频上传
  • 国产低代码框架zdppy开发笔记001 zdppy_api快速入门
  • 《鸿蒙HarmonyOS应用开发从入门到精通(第2版)》学习笔记——HarmonyOS架构介绍
  • 力扣-数据结构-8【算法学习day.79】
  • 石岩路边理发好去处
  • Kerberos用户认证-数据安全-简单了解-230403
  • 二十三种设计模式-工厂方法模式
  • 【UE5】UnrealEngine源码构建1:tag为5.3.2源码clone
  • 与你共度的烟火日常
  • 开源即时通讯IM框架MobileIMSDK的鸿蒙NEXT端开发快速入门
  • 使用 `@Async` 实现 Spring Boot 异步编程
  • 打造多元化服务体系,拉卡拉助力传统商家提升数字化经营效能
  • 《计算机网络A》单选题-复习题库
  • neo4j修改文字字体大小
  • 2024的第1篇也是最后1篇
  • spring boot 异步线程池的使用
  • [2025 测试] 如何关闭 IPhone 丢失模式