线程池是一种在程序运行时创建和管理线程的机制,它用于提高多线程程序的性能和响应能力。通过线程池,可以避免频繁创建和销毁线程的开销,同时可以有效地控制并发线程的数量,提高资源的利用率。下面是对线程池的工作原理和细节的解读:
工作原理
-
初始化线程池 (
threadpool
构造函数)- 创建一个具有指定线程数量和最大请求队列长度的线程池。
- 为每个线程分配一个
pthread_t
标识符,并创建这些线程。 - 将创建的线程设置为脱离状态(detached),这样线程结束时不会占用系统资源。
- 初始化一个工作队列(
std::list<T*>
),用于存储待处理的任务。 - 初始化一个互斥锁(
locker
),用于保护工作队列,确保线程安全地访问队列。 - 初始化一个信号量(
m_queuestat
),用于在有新任务加入队列时通知工作线程。
-
添加任务 (
append
方法)- 当有新任务(
T* request
)需要处理时,调用append
方法将其加入工作队列。 - 在添加任务前,会检查队列是否已满(是否达到
m_max_requests
指定的最大长度)。 - 如果队列未满,任务会被加入队列,并且互斥锁会解锁。
- 之后,信号量
m_queuestat
会被触发,通知工作线程有新任务到来。
- 当有新任务(
-
处理任务 (
worker
和run
方法)- 每个工作线程都会调用
worker
方法,该方法内部调用run
方法开始执行任务。 run
方法在一个循环中运行,直到线程池被停止。- 工作线程会等待信号量
m_queuestat
通知,表示有新任务加入队列。 - 当有任务时,工作线程会获取互斥锁,从队列中取出一个任务,并执行该任务的
process
方法。 - 执行完任务后,线程会释放互斥锁,并继续等待下一个任务。
- 每个工作线程都会调用
-
销毁线程池 (
threadpool
析构函数)- 当线程池不再需要时,会调用析构函数来清理资源。
- 设置
m_stop
标志为true
,通知所有工作线程停止工作。 - 等待所有工作线程结束。
- 释放工作队列和线程数组占用的内存。
细节
- 线程创建: 使用
pthread_create
在构造函数中创建线程,并将线程的标识符存储在m_threads
数组中。 - 线程脱离: 使用
pthread_detach
将线程设置为脱离状态,这样线程在结束时会自动清理资源。 - 任务队列: 使用
std::list
作为任务队列,因为它提供了高效的插入和删除操作。 - 互斥锁: 使用
locker
类(可能是一个封装了std::mutex
的类)来保护对任务队列的访问,确保线程安全。 - 信号量: 使用
sem
类(可能是一个封装了 POSIX 信号量的类)来同步任务的添加和处理。 - 异常处理: 在构造函数中,如果线程创建或内存分配失败,会抛出异常。
通过这种设计,线程池能够有效地管理线程的生命周期,减少线程创建和销毁的开销,同时提供一种简单的方式来管理并发任务。