3.1.1 池式组件:线程池

image
1.什么是线程池?
线程池是一种维持并管理固定数量线程的资源池。通过复用线程来执行多个任务,避免频繁创建/销毁线程带来的开销,并提高并发任务处理效率。

2.线程池的组成
生产者(Producer):提交耗时或异步任务的线程或模块。

任务队列(Task Queue):用于存放任务上下文与回调函数(通常封装为 std::function<void()> 或类似类型)。

消费者(Worker / 线程池中的线程):从任务队列取出任务并执行,负责线程调度与生命周期管理。

3.线程池解决的问题
异步执行耗时任务,避免阻塞主线程或核心工作线程。

充分利用多核 CPU,通过并行执行提升吞吐量。

限制并发线程数量,防止系统资源耗尽。

降低线程频繁创建与销毁的开销,提高性能与稳定性。

4.线程池如何工作
生产者将任务提交到任务队列;线程池内部的固定数量线程不断从队列中取出任务并执行。通常配合条件变量或信号量实现任务等待与唤醒。

5.线程数如何选择
CPU 密集型任务(以计算为主):线程数 ≈ CPU 核心数(或略多于核心数)。

I/O 密集型任务(以等待为主):经验公式为 2 * CPU 核心数,或根据比例估算: (线程等待时间 + CPU 运算时间) * CPU 核心数 / CPU 运算时间。 选择目标:尽量保持 CPU 在高利用但不过载、避免大量上下文切换。

6.为什么维持固定数量线程?
超过一定数量后,线程增多不会带来性能提升,反而增加上下文切换和系统开销。

固定线程数量能稳定资源使用,降低创建/销毁开销,提升性能稳定性。

7.手写线程池(设计思路)
实现线程池通常包括三部分:接口设计、数据结构设计、具体编码实现。

接口设计(对外 API)

构造与析构:创建指定数量线程,优雅停止并加入线程。

submit / enqueue:提交任务(支持返回值和异常传播,如使用 std::future)。

shutdown / stop:停止接受新任务并优雅退出,或强制停止。

配置接口:设置线程数量、队列容量、任务超时或拒绝策略(可选)。

数据结构设计

任务封装类型:例如 std::function<void()> 或模板化包装为可以返回值的任务。

任务队列:线程安全队列(单队列或多队列策略),配合互斥锁(std::mutex)与条件变量(std::condition_variable)。

状态标志:标识线程池运行/停止状态,便于在停止时唤醒所有等待线程。

具体编码

我们将分别实现单队列和双队列两种线程池,并对比其优缺点。

8.单队列线程池实现
设计思路:所有工作线程共享同一个任务队列,通过互斥锁和条件变量保证线程安全。生产者向队列中 push 任务,消费者(工作线程)从队列中 pop 任务执行。

posted @ 2026-03-24 10:38  Xiaomostream  阅读(5)  评论(0)    收藏  举报