首页
学习
活动
专区
圈层
工具
发布
社区首页 >专栏 >C++ 如何实现线程池?给出大体思路?

C++ 如何实现线程池?给出大体思路?

原创
作者头像
代码小李
发布2025-01-27 19:06:18
发布2025-01-27 19:06:18
6330
举报

在 C++ 中实现线程池是一种常见的多线程编程技术,用于管理和复用一组工作线程,以提高程序的性能和资源利用率。线程池的基本思路是预先创建一组线程,并将任务提交到一个任务队列中,线程从队列中获取任务并执行。

1. 线程池的大体思路

1.1 主要组件
  • 线程池:管理一组工作线程。
  • 任务队列:存储待处理的任务。
  • 工作线程:从任务队列中获取任务并执行。
  • 同步机制:确保线程安全,如互斥锁(std::mutex)、条件变量(std::condition_variable)等。
1.2 工作流程
  1. 初始化:创建线程池对象,初始化任务队列和工作线程。
  2. 任务提交:将任务添加到任务队列中。
  3. 任务执行:工作线程从任务队列中获取任务并执行。
  4. 线程管理:根据需要动态调整线程数量,如增加或减少线程。
  5. 关闭线程池:停止所有工作线程,释放资源。

2. 示例代码

以下是一个简单的线程池实现示例:

代码语言:cpp
复制
#include <iostream>
#include <thread>
#include <vector>
#include <queue>
#include <functional>
#include <future>
#include <atomic>
#include <mutex>
#include <condition_variable>

class ThreadPool {
public:
    ThreadPool(size_t threads) : stop(false) {
        for (size_t i = 0; i < threads; ++i) {
            workers.emplace_back([this] {
                while (true) {
                    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() {
        {
            std::unique_lock<std::mutex> lock(queue_mutex);
            stop = true;
        }
        condition.notify_all();
        for (std::thread &worker : workers) {
            worker.join();
        }
    }

    template<class F, class... Args>
    auto enqueue(F&& f, Args&&... args) -> std::future<decltype(f(args...))> {
        using return_type = decltype(f(args...));
        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;
    }

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

    std::mutex queue_mutex;
    std::condition_variable condition;
    std::atomic<bool> stop;
};

// 示例任务函数
void taskFunction(int id) {
    std::cout << "Task " << id << " is running on thread " << std::this_thread::get_id() << std::endl;
}

int main() {
    ThreadPool pool(4);

    for (int i = 0; i < 10; ++i) {
        pool.enqueue(taskFunction, i);
    }

    return 0;
}

3. 代码解释

  • ThreadPool 类
    • 构造函数:创建指定数量的工作线程。
    • 析构函数:停止所有工作线程并等待它们完成。
    • enqueue 方法:将任务添加到任务队列中,并返回一个 std::future 对象,用于获取任务的返回值。
  • 工作线程
    • 每个工作线程在一个无限循环中运行,从任务队列中获取任务并执行。
    • 使用 std::condition_variable 等待任务队列中有任务可用。
  • 任务队列
    • 使用 std::queue 存储任务。
    • 使用 std::mutexstd::condition_variable 确保线程安全。

4. 总结

  • 线程池:管理一组工作线程,提高多线程程序的性能和资源利用率。
  • 任务队列:存储待处理的任务,确保线程安全。
  • 工作线程:从任务队列中获取任务并执行。
  • 同步机制:使用互斥锁和条件变量确保线程安全。

原创声明:本文系作者授权腾讯云开发者社区发表,未经许可,不得转载。

如有侵权,请联系 cloudcommunity@tencent.com 删除。

原创声明:本文系作者授权腾讯云开发者社区发表,未经许可,不得转载。

如有侵权,请联系 cloudcommunity@tencent.com 删除。

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • 1. 线程池的大体思路
    • 1.1 主要组件
    • 1.2 工作流程
  • 2. 示例代码
  • 3. 代码解释
  • 4. 总结
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档