1. C++线程池实现详解
线程池是现代多线程编程中不可或缺的工具,它能有效管理线程资源,避免频繁创建和销毁线程带来的性能开销。下面我将从基础实现开始,逐步深入讲解几种典型的C++线程池实现方案。
1.1 基础线程池实现
基础线程池的核心组件包括:
- 线程安全的任务队列
- 工作线程集合
- 任务提交接口
cpp复制#include <future>
#include <list>
#include <queue>
#include <thread>
#include <vector>
#include <mutex>
#include <condition_variable>
// 线程安全队列
template <typename T>
class threadsafe_queue {
std::queue<T> data_queue;
std::mutex m;
std::condition_variable cv;
public:
void push(T new_value) {
std::lock_guard<std::mutex> lk(m);
data_queue.push(std::move(new_value));
cv.notify_one();
}
bool try_pop(T& value) {
std::lock_guard<std::mutex> lk(m);
if (data_queue.empty()) return false;
value = std::move(data_queue.front());
data_queue.pop();
return true;
}
};
这个线程安全队列使用了互斥锁(mutex)和条件变量(condition_variable)来保证线程安全。push操作会通知一个等待的线程,而try_pop则是非阻塞的。
注意:在实际应用中,我们通常会添加wait_and_pop方法来实现阻塞式获取任务,避免忙等待。
1.2 线程池核心实现
cpp复制class thread_pool {
std::atomic_bool done;
threadsafe_queue<std::function<void()>> work_queue;
std::vector<std::thread> threads;
void worker_thread() {
while (!done) {
std::function<void()> task;
if (work_queue.try_pop(task)) {
task();
} else {
std::this_thread::yield();
}
}
}
public:
thread_pool() : done(false) {
unsigned const thread_count = std::thread::hardware_concurrency();
try {
for (unsigned i = 0; i < thread_count; ++i) {
threads.push_back(std::thread(&thread_pool::worker_thread, this));
}
} catch (...) {
done = true;
throw;
}
}
~thread_pool() {
done = true;
for (auto& t : threads) {
if (t.joinable()) t.join();
}
}
void submit(std::function<void()> task) {
work_queue.push(std::move(task));
}
};
这个基础线程池有几个关键点:
- 使用std::atomic_bool done作为停止标志
- 线程数量根据硬件并发数确定
- 工作线程不断尝试从队列获取任务执行
- 析构时会等待所有线程完成
实际使用中发现,这种基础实现有几个问题:无法获取任务返回值、无法设置任务优先级、线程可能忙等待。下面我们逐步改进。
需要模型API调用? 免费领10W Token,多模型网关一键接入 Claude、DeepSeek 等主流模型。
2. 支持任务优先级的线程池
2.1 优先级任务队列实现
cpp复制struct PriorityTask {
int pr
