1. 为什么需要线程池?
在现代软件开发中,并发编程已经成为提升程序性能的关键手段。但直接使用裸线程(raw thread)会面临几个棘手问题:
-
线程创建销毁开销大:每次创建线程需要分配栈空间(通常1-8MB)、初始化线程描述符等内核对象,在Linux下实测创建10万个线程耗时约12秒,销毁同样耗时。
-
线程数量失控风险:假设每个HTTP请求创建一个线程,当突发大流量时可能瞬间创建数千线程,导致系统资源耗尽。我曾遇到过一个生产环境案例:由于未做线程数限制,系统在流量高峰时创建了3000+线程,最终因内存不足崩溃。
-
线程调度不可控:操作系统调度大量线程会产生显著的上下文切换开销。测试表明当活跃线程数超过CPU核心数2倍时,调度开销开始显著影响性能。
线程池通过资源预分配+任务队列的架构完美解决这些问题。我们的实现方案具有以下特点:
- 零第三方依赖:仅使用C++11标准库,避免引入boost等重型库的依赖
- 跨平台一致性:基于标准库的线程原语,在Windows/Linux/macOS表现一致
- 类型安全接口:模板方法支持任意可调用对象,编译期检查类型安全
- 高效任务调度:条件变量实现精准唤醒,避免忙等待(busy-waiting)
需要模型API调用? 免费领10W Token,多模型网关一键接入 Claude、DeepSeek 等主流模型。
2. 核心架构设计
2.1 类结构设计
cpp复制class AsyncThreadPool {
public:
explicit AsyncThreadPool(size_t thread_num);
~AsyncThreadPool();
template<typename Func, typename... Args>
void submit_task(Func&& func, Args&&... args);
// 禁用拷贝构造和赋值
AsyncThreadPool(const AsyncThreadPool&) = delete;
AsyncThreadPool& operator=(const AsyncThreadPool&) = delete;
private:
void worker_loop();
std::vector<std::thread> workers_;
std::queue<std::function<void()>> tasks_;
std::mutex mtx_;
std::condition_variable cv_;
bool stop_flag_;
};
设计要点解析:
- 资源管理:遵循RAII原则,构造函数初始化资源,析构函数确保安全释放
- 线程安全:
std::mutex保护任务队列和停止标志std::condition_variable实现高效等待
- 任务抽象:
std::function<void()>统一封装各类可调用对象 - 防误用设计:显式删除拷贝操作,避免线程池被意外复制
2.2 线程生命周期管理
工作线程的核心逻辑在worker_loop()中实现:
cpp复制void worker_loop() {
while (true) {
std::unique_lock
