高效并发编程:在C++中实现线程池

news/2024/9/15 5:51:33 标签: c++, java, 开发语言

高效并发编程:在C++中实现线程池

在现代软件开发中,线程池是一种常用的并发编程技术,能够有效管理和调度多个线程,提高系统性能和资源利用率。本文将详细介绍什么是线程池,并提供在C++中实现线程池的实用方法和示例。

什么是线程池?

线程池是一组预先创建的线程,这些线程在需要时可以被重复使用,而不是为每个任务单独创建和销毁线程。通过这种方式,线程池可以减少线程创建和销毁的开销,提高系统的响应速度和资源利用率。

线程池的优势
  1. 提高性能:通过重用线程,减少了线程创建和销毁的开销。
  2. 资源管理:限制线程数量,防止资源耗尽。
  3. 任务调度:通过任务队列和调度算法,优化任务执行顺序。
在C++中实现线程池

在C++中实现线程池可以通过标准库中的线程和同步工具。以下是一个简单的线程池实现示例。

1. 线程池类的定义

首先,我们定义一个线程池类,包含线程池的基本结构和成员变量。

#include <vector>
#include <queue>
#include <thread>
#include <mutex>
#include <condition_variable>
#include <functional>
#include <future>

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

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

private:
    std::vector<std::thread> workers;
    std::queue<std::function<void()>> tasks;

    std::mutex queue_mutex;
    std::condition_variable condition;
    bool stop;
};

2. 线程池的构造函数和析构函数

在构造函数中,我们初始化工作线程,并启动它们以等待任务。在析构函数中,我们确保所有线程都能正确退出。

ThreadPool::ThreadPool(size_t threads) : stop(false) {
    for (size_t i = 0; i < threads; ++i) {
        workers.emplace_back([this] {
            for (;;) {
                std::function<void()> 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 = std::move(this->tasks.front());
                    this->tasks.pop();
                }
                task();
            }
        });
    }
}

ThreadPool::~ThreadPool() {
    {
        std::unique_lock<std::mutex> lock(queue_mutex);
        stop = true;
    }
    condition.notify_all();
    for (std::thread &worker : workers) {
        worker.join();
    }
}

3. 任务入队函数

我们使用模板函数enqueue将任务添加到任务队列中,并返回一个std::future对象,以便获取任务的执行结果。

template<class F, class... Args>
auto ThreadPool::enqueue(F&& f, Args&&... args) -> std::future<typename std::result_of<F(Args...)>::type> {
    using return_type = typename std::result_of<F(Args...)>::type;

    auto task = std::make_shared<std::packaged_task<return_type()>>(
        std::bind(std::forward<F>(f), std::forward<Args>(args)...)
    );

    std::future<return_type> res = task->get_future();
    {
        std::unique_lock<std::mutex> lock(queue_mutex);
        if (stop) throw std::runtime_error("enqueue on stopped ThreadPool");
        tasks.emplace([task]() { (*task)(); });
    }
    condition.notify_one();
    return res;
}

4. 使用线程池

以下是一个使用线程池的示例,展示了如何创建线程池并提交任务。

#include <iostream>

int main() {
    ThreadPool pool(4);

    auto result1 = pool.enqueue([] { return 1 + 1; });
    auto result2 = pool.enqueue([](int a, int b) { return a + b; }, 2, 3);

    std::cout << "Result 1: " << result1.get() << std::endl;
    std::cout << "Result 2: " << result2.get() << std::endl;

    return 0;
}

总结

线程池是C++并发编程中的一个重要工具,通过预先创建和重用线程,可以显著提高系统性能和资源利用率。本文介绍了线程池的基本概念和优势,并提供了一个简单的线程池实现示例。希望这些内容能帮助你在实际项目中实现高效的任务调度和并发处理。

如果你有任何问题或需要进一步的帮助,请随时联系我!


http://www.niftyadmin.cn/n/5633946.html

相关文章

nginx平滑升级与回滚

华子目录 升级实验环境准备测试内容准备实验要求实验步骤1.解压包2.检测1.26版本的环境3.make编译4.备份之前的nginx启动脚本5.将1.26中的nginx启动脚本覆盖掉1.24中的6.kill -USR2 旧主进程pid7.kill -WINCH 旧主进程pid 实验测试 回滚1.kill -HUP 旧主进程pid2.kill -WINCH 新…

java转发IP/TCP和IP/UDP数据包

java转发IP/TCP和IP/UDP数据包 程序原理程序代码程序如何安装使用如何搭建服务器如何使用客户端 程序原理 读取头部信息&#xff0c;创建Socket 将IP数据发送给服务器 收到数据加入头部信息返回 程序代码 查看 github 程序如何安装使用 文件说明&#xff1a; build/XiGuaV…

jenkins web界面构建job时平台展现的时间是6点,可是当前北京是14点,如何调整这个时间,如何调整 Jenkins 的时间显示

要在 Jenkins 中设置时区以确保打印的时间与北京时间一致&#xff0c;可以按照以下步骤操作&#xff1a; 方法 1&#xff1a;通过 Jenkins 系统设置 登录 Jenkins&#xff1a; 使用管理员账户登录到 Jenkins 的 web 界面。进入系统设置&#xff1a; 点击左侧菜单中的“管理 J…

python网络爬虫(一)——网络爬虫基本原理

1.使用Beautiful Soup解析网页 通过request库已经抓取到网页源码&#xff0c;接下来要从源码中找到并提取数据。Beautiful Soup是python的一个库&#xff0c;其主要功能是从网页中抓取数据。Beautiful Soup目前已经被移植到bs4库中&#xff0c;也就是说在导入Beautiful Soup时需…

安卓项目打包与发版说明-笔记

项目打包与发版说明 Android Studio 打包 1.打包debug版 在调试完成后&#xff0c;点击编辑器的上方Build选项&#xff0c;然后依次选择 ->Build Bundle(s) / APK(s) -> Build APK(s) 打包完成后在控制台信息处点击信息框中的locate&#xff0c;在文件管理器中浏览&a…

力扣237题详解:删除链表中的节点的模拟面试问答

在本篇文章中&#xff0c;我们将详细解读力扣第237题“删除链表中的节点”。通过学习本篇文章&#xff0c;读者将掌握如何在单链表中删除给定的节点&#xff0c;并了解相关的复杂度分析和模拟面试问答。每种方法都将配以详细的解释&#xff0c;以便于理解。 问题描述 力扣第2…

桶排序【算法 14】

桶排序算法详解 桶排序&#xff08;Bucket Sort&#xff09;是一种基于分配的排序算法&#xff0c;适用于均匀分布在特定范围内的数据。其核心思想是将输入数据分到若干个桶&#xff08;Bucket&#xff09;中&#xff0c;每个桶分别进行排序&#xff0c;最后合并桶内的元素形成…

《高等代数》范德蒙德行列式的应用

说明&#xff1a;此文章用于本人复习巩固&#xff0c;如果也能帮助到大家那就更加有意义了。 注&#xff1a;范德蒙德行列式的简单应用及其变形。 范德蒙德行列式的计算公式&#xff1a; 注&#xff1a;&#xff08;1&#xff09;用大下标减去小下标。 &#xff08;2&#xf…