前言
在高并发编程场景中,线程池是提升程序性能、降低资源消耗的核心组件。不同于固定大小的线程池,缓存线程池(CachedThreadPool) 能够根据任务量动态调整线程数量 ------ 任务繁忙时创建新线程,空闲时回收多余线程,兼顾了高并发处理能力和资源利用率。
一、缓存线程池的核心设计理念
缓存线程池的核心目标是解决任务量波动场景下的线程资源高效管理,其设计理念围绕四大核心目标展开:
- 动态扩缩容:核心线程数保持稳定,任务积压时临时创建新线程,空闲线程超时时自动回收;
- 任务异步调度:通过线程安全的任务队列解耦任务提交与执行;
- 资源可控:限制最大线程数,避免无限制创建线程导致系统资源耗尽;
- 优雅退出:支持线程池停止时等待所有任务执行完毕,避免任务丢失。
本文实现的缓存线程池核心结构如下:
- 线程安全的任务队列(
SyncQueue):存储待执行的任务,支持阻塞 / 超时获取任务; - 线程管理模块:维护线程集合,统计核心线程、空闲线程、当前线程数;
- 动态扩缩容逻辑:根据空闲线程数和任务队列状态创建 / 回收线程;
- 任务提交接口:支持普通任务和带返回值的异步任务提交。
二、核心组件拆解
2.1 线程安全的任务队列(SyncQueue)
任务队列是线程池的 "消息中枢",需要保证多线程下的安全读写,同时支持 "队列满时阻塞提交""队列空时阻塞获取""超时退出" 等核心能力。
核心实现细节
cpp
#include <list>
#include <vector>
#include <deque>
#include <queue>
#include <mutex>
#include <condition_variable>
#include <iostream>
using namespace std;
#include "Logger.hpp"
#define QUESTOP 2
#define QUEEMPTY 1
#define ok 0
#ifndef SYNC_QUEUE_1_HPP
#define SYNC_QUEUE_1_HPP
namespace tulun
{
static const size_t MaxTaskCount = 500;
template <class T> // Task = 队列里存的类型
class SyncQueue
{
private:
std::deque<T> m_queue; // 底层容器:双端队列(存任务),头尾操作O(1)
mutable std::mutex m_mutex; // 互斥锁,保护队列所有共享操作
std::condition_variable m_notEmpty; // 条件变量:队列非空,唤醒消费者线程
std::condition_variable m_notFull; // 条件变量:队列未满,唤醒生产者线程
std::condition_variable m_waitStop; // 条件变量:等待队列为空再停止
int m_maxSize; // 队列最大容量上限
bool m_needStop; // true停止标记(初始为false)
int m_waitTime = 100; // 超时等待时间,单位ms
// 判断队列是否满
bool IsFull() const
{
bool full = m_queue.size() >= m_maxSize;
// LOG_INFO << "full: " << full;
// LOG_FATAL<<"full: "<<full;
return full;
}
// 判断队列是否为空
bool IsEmpty() const
{
bool empty = m_queue.empty();
// LOG_INFO << "empty: " << empty;
return empty;
}
template <class F> // F 传进来的参数类型
int Add(F &&task)
{
std::unique_lock<std::mutex> locker(m_mutex); // 加锁
// if(IsFull()) return ;
// m_notFull.wait(locker,[this]()->bool{
// return m_needStop || !IsFull();
// });
// 队列满 && 不停止 → 等待
// while (!m_needStop && IsFull())
//{
// auto tag = m_notFull.wait_for(locker, std::chrono::milliseconds(m_waitTime)); // 阻塞,等待不满
// if (tag == std::cv_status::timeout && IsFull())
// {
// return 1;
// }
//}
// 带超时等待:队列未满 或 线程池停止 就解除阻塞
auto tag = m_notFull.wait_for(locker,
std::chrono::milliseconds(m_waitTime),
[this]() -> bool
{
return m_needStop || !IsFull();
}); // lambda 返回 true → 停止等待,继续往下执行代码
if (m_needStop)
{
return 2; // 线程池已停止,入队失败
}
if (!tag) // 超时队列依旧满,触发拒绝策略
{
return 1; // IsFull() true;
}
// 完美转发,零拷贝将任务放入队列尾部
m_queue.push_back(std::forward<F>(task)); // 放入队列
m_notEmpty.notify_all(); // 唤醒消费者:有活干了!
return 0;
}
public:
SyncQueue(int maxsize = MaxTaskCount)
: m_maxSize(maxsize),
m_needStop(false)
{
}
~SyncQueue()
{
if (!m_needStop)
{
Stop();
}
}
SyncQueue(const SyncQueue &) = delete;
SyncQueue &operator=(const SyncQueue &) = delete;
// 生产者 Put(放任务)
int Put(const T &task)
{
return Add(task);
}
int Put(T &&task)
{
return Add(std::forward<T>(task));
}
// 消费者 Take(取任务)
int Take(T &task)
{
std::unique_lock<std::mutex> locker(m_mutex); // 加锁
// 队列空 && 不停止 → 等待
// while (!m_needStop && IsEmpty())
// {
// m_notEmpty.wait(locker); // 阻塞,等待不为空
// }
bool tag = m_notEmpty.wait_for(locker,
std::chrono::milliseconds(m_waitTime),
[this]() -> bool
{
return m_needStop || !IsEmpty();
});
if (m_needStop)
{
return 2;
}
if (!tag)
{
return 1;
}
task = m_queue.front();
m_queue.pop_front(); // 取出任务
m_notFull.notify_all(); // 唤醒生产者:有空位啦!
return 0;
}
// 批量取任务(高性能)
int Task(std::deque<T> &tqu)
{
std::unique_lock<std::mutex> locker(m_mutex);
bool tag = m_notEmpty.wait_for(locker,
std::chrono::milliseconds(m_waitTime),
[this]() -> bool
{
return m_needStop || !IsEmpty();
});
if (m_needStop)
{
return 2;
}
if (!tag)
{
return 1;
}
tqu = std::move(m_queue); // 【一次性拿走所有任务】
m_notFull.notify_all();
return 0;
}
// 立即停止:直接置位标记,唤醒所有线程
void Stop()
{
{
std::unique_lock<std::mutex> locker(m_mutex);
m_needStop = true;
}
// 锁外唤醒!性能优化点
m_notEmpty.notify_all();
m_notFull.notify_all();
}
// 等待队空停止:处理完所有任务再停止(业务最常用)
void WaitQueueEmptyStop()
{
std::unique_lock<std::mutex> locker(m_mutex);
// 等待队列所有任务消费完毕
while (!IsEmpty())
{
m_waitStop.wait_for(locker, std::chrono::milliseconds(m_waitTime));
}
m_needStop = true;
m_notFull.notify_all();
m_notEmpty.notify_all();
}
bool Empty() const
{
std::unique_lock<std::mutex> locker(m_mutex);
return m_queue.empty();
}
bool Full() const
{
std::unique_lock<std::mutex> locker(m_mutex);
return m_queue.size() >= m_maxSize;
}
size_t Size() const
{
std::unique_lock<std::mutex> locker(m_mutex);
return m_queue.size();
}
size_t Count() const
{
return m_queue.size();
}
};
} // namespace tulun
#endif
关键设计点
- 双条件变量 :
m_notEmpty供消费者(线程池工作线程)等待,m_notFull供生产者(任务提交线程)等待,减少无效唤醒; - 超时等待 :
wait_for替代无限等待,避免线程永久阻塞; - 移动语义 :
Put(T &&task)支持右值引用,减少任务拷贝开销; - 异常安全 :通过
unique_lock管理锁,保证异常时锁自动释放。
2.2 缓存线程池核心(CachedThreadPool)
线程池的核心逻辑集中在线程管理 和任务调度,主要包含以下模块:
2.2.1 核心成员变量
cpp
class CachedThreadPool {
public:
using Task = std::function<void(void)>;
private:
// static const int KeepAliveTime = 60; // s;
static int KeepAliveTime;
std::unordered_map<std::thread::id, std::shared_ptr<std::thread>> m_threadgroup;// 线程管理表
int m_coreThreadSize = 4; // 核心线程(永远不死)
int m_maxThreadSize = std::thread::hardware_concurrency();// 最大线程数
mutable std::mutex m_mutex;
std::condition_variable m_threadExit;
std::atomic<int> m_idleThreadSize = 0;// 空闲线程数量
std::atomic<int> m_curThreadSize = 0;// 当前总线程数
tulun::SyncQueue<Task> m_queue; // 任务队列
std::atomic<bool> m_running = false; // true;// 运行标记
std::once_flag m_flag;
};
2.2.2 CachedThreadPool.hpp
cpp
#include "SyncQueue_1.hpp"
#include <functional>
#include <map>
#include <unordered_map>
#include <thread>
#include <memory>
#include <mutex>
#include <condition_variable>
#include <atomic>
#include <future>
using namespace std;
#ifndef CACHED_THREAD_POOL_HPP
#define CACHED_THREAD_POOL_HPP
namespace tulun
{
class CachedThreadPool
{
public:
using Task = std::function<void(void)>;
private:
// static const int KeepAliveTime = 60; // s;
static int KeepAliveTime;
std::unordered_map<std::thread::id, std::shared_ptr<std::thread>> m_threadgroup;// 线程管理表
int m_coreThreadSize = 4; // 核心线程(永远不死)
int m_maxThreadSize = std::thread::hardware_concurrency();// 最大线程数
mutable std::mutex m_mutex;
std::condition_variable m_threadExit;
std::atomic<int> m_idleThreadSize = 0;// 空闲线程数量
std::atomic<int> m_curThreadSize = 0;// 当前总线程数
tulun::SyncQueue<Task> m_queue; // 任务队列
std::atomic<bool> m_running = false; // true;// 运行标记
std::once_flag m_flag;
void Start(int numthreads);
void RunInThread();
void StopThreadGroup();
void newThread();
public:
CachedThreadPool(int initnumthreads = 2, int taskqueuesize = MaxTaskCount);
~CachedThreadPool();
void Stop();
void AddTask(Task &&task);
void AddTask(const Task &task);
void PrintInfo() const
{
std::lock_guard<std::mutex> locker(m_mutex);
cout << "m_core: " << m_coreThreadSize << endl;
cout << "m_idle: " << m_idleThreadSize << endl;
cout << "m_cur: " << m_curThreadSize << endl;
cout << "m_max: " << m_maxThreadSize << endl;
cout<<"-------------------------------"<<endl;
}
template <class Func, class... Args>
auto submit(Func &&func, Args &&...args)
{
// typedef decltype(func(args...)) RetType;
// using RetType = decltype(func(args...));
// std::packaged_task<RetType()> task(
// std::bind(
// std::forward<Func>(func),
// std::forward<Args>(args)...)
//);
// 正确推导返回值(支持成员函数)
using RetType = decltype(std::invoke(std::forward<Func>(func), std::forward<Args>(args)...));
// 封装任务
auto task = std::make_shared<std::packaged_task<RetType()>>(
[func = std::forward<Func>(func), ... args = std::forward<Args>(args)]() mutable
{
return std::invoke(func, args...);
});
std::future<RetType> result = task->get_future();
if (m_queue.Put([task]() -> void
{ (*task)(); }) != 0)
{
LOG_ERROR << "Add task run task";
(*task)();
}
newThread();
return result;
}
int getThreadNUm() const;
};
}
#endif
2.2.3线程池初始化(Start)
初始化时创建核心线程,作为常驻线程处理任务:
cpp
void CachedThreadPool::Start(int numthreads)
{
m_running = true;
m_curThreadSize = numthreads;
// 创建核心线程
for (int i = 0; i < numthreads; ++i)
{
auto tha = std::make_shared<std::thread>(&CachedThreadPool::RunInThread, this);
std::thread::id tid = tha->get_id();
m_threadgroup.emplace(tid, tha);
// 初始时所有线程都处于空闲状态(m_idleThreadSize 增加)。
++m_idleThreadSize;
}
}
2.2.4 工作线程逻辑(RunInThread)
工作线程的核心逻辑是 "循环获取任务执行,空闲超时则回收":
cpp
int CachedThreadPool::KeepAliveTime = 60;
void CachedThreadPool::RunInThread()
{
auto tid = std::this_thread::get_id();
auto startTime = std::chrono::high_resolution_clock().now();
while (m_running)
{
Task task;
if (m_queue.Empty())
{
auto now = std::chrono::high_resolution_clock().now();
auto intervalTime =
std::chrono::duration_cast<std::chrono::seconds>(now - startTime).count();
std::lock_guard<std::mutex> locker(m_mutex);
if (intervalTime >= KeepAliveTime && m_curThreadSize > m_coreThreadSize)
{
// m_threadgroup.find(tid)->second->join();// error;
// 超时且当前线程数超过核心数 -> 该线程退出
m_threadgroup.find(tid)->second->detach();
// detach 后线程对象仍然在 m_threadgroup 中
m_threadgroup.erase(tid);
m_curThreadSize--;
m_idleThreadSize--;
// m_threadExit.notify_all();//????需要吗
return;
}
}
// 当队列空且未停止时,Take会阻塞或超时返回非
// 返回值:0成功,1超时无任务,2停止
if (m_queue.Take(task) != 0)
{
continue;
}
if (m_running && task)
{
m_idleThreadSize--; // 即将执行任务,空闲数减1
task(); // 执行任务
m_idleThreadSize++; // 执行完毕,空闲数加1
// 重置空闲计时起点(刚执行完任务,认为现在开始进入空闲期)
startTime = std::chrono::high_resolution_clock().now();
}
}
}
2.2.5 动态创建线程(newThread)
当空闲线程不足且未达最大线程数时,创建新线程:
cpp
// 扩容
void CachedThreadPool::newThread()
{
std::lock_guard<std::mutex> locker(m_mutex);
if (m_idleThreadSize <= 0 && m_curThreadSize < m_maxThreadSize)
{
auto tha = std::make_shared<std::thread>(&CachedThreadPool::RunInThread, this);
std::thread::id tid = tha->get_id();
m_threadgroup.emplace(tid, tha);
m_idleThreadSize++;
m_curThreadSize++;
}
}
2.2.6 任务提交接口
支持两种任务提交方式:普通任务(无返回值)和异步任务(带返回值)。
普通任务提交:
cpp
void CachedThreadPool::AddTask(Task &&task)
{
if (m_queue.Put(std::forward<Task>(task)) != 0)
{
LOG_INFO << "task()";
task();
}
newThread(); // 尝试创建新线程
}
void CachedThreadPool::AddTask(const Task &task)
{
if (m_queue.Put(task) != 0)
{
LOG_INFO << "task()";
task();
}
newThread();
}
异步任务提交(带返回值) :利用 packaged_task 和 future 实现异步结果获取:
cpp
template <class Func, class... Args>
auto submit(Func &&func, Args &&...args)
{
// 正确推导返回值(支持成员函数)
using RetType = decltype(std::invoke(std::forward<Func>(func), std::forward<Args>(args)...));
// 封装任务
auto task = std::make_shared<std::packaged_task<RetType()>>(
[func = std::forward<Func>(func), ... args = std::forward<Args>(args)]() mutable
{
return std::invoke(func, args...);
});
std::future<RetType> result = task->get_future();
if (m_queue.Put([task]() -> void
{ (*task)(); }) != 0)
{
LOG_ERROR << "Add task run task";
(*task)();
}
newThread();
return result;
}
2.2.7 优雅停止(StopThreadGroup)
停止线程池时,需等待所有任务执行完毕,再回收所有线程:
cpp
void CachedThreadPool::StopThreadGroup()
{
// 等待队列消费完毕,然后设置停止标志
m_queue.WaitQueueEmptyStop();
m_coreThreadSize = 0;
KeepAliveTime = 0;// 强制回收所有空闲线程
std::unique_lock<std::mutex> locker(m_mutex);
while (!m_threadgroup.empty())
{
m_threadExit.wait_for(locker, std::chrono::milliseconds(100));
}
m_running = false;
}
void CachedThreadPool::Stop()
{
std::call_once(m_flag, std::bind(&CachedThreadPool::StopThreadGroup, this));
}
2.2.8 构造+析构
cpp
CachedThreadPool::CachedThreadPool(int initnumthreads, int taskqueuesize)
: m_coreThreadSize(initnumthreads),
// m_idleThreadSize(0),
// m_maxThreadSize(0),
// m_curThreadSize(0),
m_queue(taskqueuesize)
// m_running(false)
{
Start(initnumthreads);
}
CachedThreadPool::~CachedThreadPool()
{
if (m_running)
{
Stop();
}
}
三、缓存线程池 vs 固定线程池:核心特性对比
| 特性 | FixedThreadPool |
CachedThreadPool |
|---|---|---|
| 线程复用 | 支持复用,但无法动态创建新线程 | 优先复用空闲线程,无空闲线程时动态创建新线程 |
| 池大小 | 固定数量(创建时指定) | 可增长,最大上限为 Integer.MAX_VALUE(或自定义上限) |
| 队列大小 | 无限制 | 无限制 |
| 超时机制 | 无空闲超时,线程常驻 | 默认空闲线程存活 60 秒,超时自动回收 |
| 适用场景 | 稳定高负载、CPU 密集型任务(避免频繁线程切换) | 大量短期异步任务、低负载波动场景 |
| 线程生命周期 | 线程池销毁前不自动销毁 | 空闲超时自动终止,避免资源浪费 |
从对比中可以看出:
FixedThreadPool适合稳定的 CPU 密集型任务,避免线程频繁创建 / 销毁带来的开销;CachedThreadPool适合短期、并发波动大的 IO 密集型任务,通过动态扩缩容平衡性能与资源消耗。
四、使用场景与最佳实践
4.1 缓存线程池的适用场景
结合特性,缓存线程池最适合以下场景:
- 大量短期任务:适合处理大量短期任务,当任务到来时尽可能创建新线程执行,空闲线程可复用,避免频繁创建 / 销毁线程的额外开销;
- 任务响应快速:适合需要快速响应的任务,可根据任务量快速创建 / 启动新线程,减少任务等待时间;
- 无需限制线程数量:适合任务到来时不限制线程数量的场景,只要内存充足,可动态创建新线程;
- 短期任务高并发:适合处理高并发的短期任务,任务完成后线程池保留空闲线程,为下一批任务做准备。
4.2 最佳实践与避坑指南
缓存线程池并非 "万能方案",高负载场景下存在明显风险,因此工程实践中需注意以下几点:
- 警惕无界队列风险:无界任务队列可能导致内存溢出、任务延迟过高,建议设置有界队列;
- 控制最大线程数:默认无上限的线程创建可能导致系统资源耗尽,需自定义最大线程数;
- 避免长时间阻塞任务:缓存线程池不适合执行长时间任务,否则会导致后续任务堆积、线程数持续膨胀;
- 推荐使用
ThreadPoolExecutor:Java/C++ 中可直接使用ThreadPoolExecutor(或其 C++ 实现),通过自定义核心线程数、最大线程数、队列大小、拒绝策略实现细粒度控制; - 扩展钩子函数 :可重载
beforeExecute/afterExecute钩子函数,实现任务执行前后的自定义操作(如日志、监控); - 线程工厂定制 :通过自定义
ThreadFactory为线程命名、设置守护线程属性,便于问题排查; - 动态调整池大小:可实现动态线程池,运行时根据任务量、CPU 使用率调整核心线程数与最大线程数。
五、缓存线程池的使用示例
以下示例展示了如何使用缓存线程池处理大规模任务(随机数生成):
cpp
#include <random>
#include <iostream>
using namespace std;
#include "Timestamp.hpp"
#include "Logger.hpp"
#include "CachedThreadPool.hpp"
static const size_t row = 10000;
static const size_t col = 100000;
std::vector<std::vector<int>> iveca, ivecb, ivecc, ivecd;
void RandInit(std::vector<int> &ivec)
{
std::random_device rd; // 真随机种子源
std::mt19937 gen(rd()); // 随机数引擎
std::uniform_int_distribution<int> dis(0, 100000); // 分布范围 [1, 100]
// int random_num = dis(gen);
// ivec.reserve(col);
for (int i = 0; i < col; ++i)
{
// ivec.push_back(rand() % 10000);
ivec.push_back(dis(gen));
}
}
void SortVec(std::vector<int> &ivec)
{
std::sort(ivec.begin(), ivec.end());
}
void SaveFile(std::vector<int> &ivec, const std::string &filename)
{
FILE *pf = fopen(filename.c_str(), "a");
if (nullptr == pf)
{
LOG_FATAL << "fopen fail \n";
exit(EXIT_FAILURE);
}
for (int i = 0; i < col; ++i)
{
fprintf(pf, "%d ", ivec[i]);
}
fprintf(pf, "\n---------------------\n");
fclose(pf);
pf = nullptr;
}
void test_funb()
{
srand(time(nullptr));
cout << "4 线程测试...." << endl;
tulun::Timestamp start, end;
start = tulun::Timestamp::Now();
{
ivecb.resize(row);
tulun::CachedThreadPool mypool(4, 500);
for (int i = 0; i < row; ++i)
{
ivecb[i].reserve(col);
// RandInit(ivecb[i]);
mypool.AddTask(std::bind(RandInit, std::ref(ivecb[i])));
if ((i + 1) % 5000 == 0)
{
mypool.PrintInfo();
}
}
}
end = tulun::Timestamp::Now();
cout << "RandInit: " << (tulun::diffMicro(end, start)) / 1000000 << "." << (tulun::diffMicro(end, start)) % 1000000 << endl;
start = tulun::Timestamp::Now();
{
tulun::CachedThreadPool mypool(4, 500);
for (int i = 0; i < row; ++i)
{
// SortVec(ivecb[i]);
mypool.AddTask(std::bind(SortVec, std::ref(ivecb[i])));
if ((i + 1) % 5000 == 0)
{
mypool.PrintInfo();
}
}
}
end = tulun::Timestamp::Now();
cout << "SortVec : " << (tulun::diffMicro(end, start)) / 1000000 << "." << (tulun::diffMicro(end, start)) % 1000000 << endl;
start = tulun::Timestamp::Now();
{
tulun::CachedThreadPool mypool(4, 500);
for (int i = 0; i < row; ++i)
{
// SaveFile(ivecb[i], "iveca.txt");
mypool.AddTask(std::bind(SaveFile, std::ref(ivecb[i]), std::string("ivecb.txt")));
if ((i + 1) % 5000 == 0)
{
mypool.PrintInfo();
}
}
}
end = tulun::Timestamp::Now();
cout << "SaveFile: " << (tulun::diffMicro(end, start)) / 1000000 << "." << (tulun::diffMicro(end, start)) % 1000000 << endl;
return;
}
void funa()
{
for (int i = 0; i < 1000; ++i)
;
std::this_thread::sleep_for(std::chrono::milliseconds(100));
}
void funb()
{
for (int i = 0; i < 100; ++i)
;
std::this_thread::sleep_for(std::chrono::milliseconds(rand() % 100));
}
void test_func()
{
{
tulun::CachedThreadPool mypool(4, 500);
for (int i = 0; i < 1000; ++i)
{
mypool.AddTask(funa);
if ((i + 1) % 100 == 0)
{
mypool.PrintInfo();
}
}
cout << "###############################" << endl;
for (int i = 0; i < 1000; ++i)
{
mypool.AddTask(funb);
if ((i + 1) % 10 == 0)
{
mypool.PrintInfo();
}
}
std::this_thread::sleep_for(std::chrono::seconds(1));
mypool.PrintInfo();
std::this_thread::sleep_for(std::chrono::seconds(1));
mypool.PrintInfo();
std::this_thread::sleep_for(std::chrono::seconds(1));
mypool.PrintInfo();
std::this_thread::sleep_for(std::chrono::seconds(1));
mypool.PrintInfo();
std::this_thread::sleep_for(std::chrono::seconds(1));
mypool.PrintInfo();
std::this_thread::sleep_for(std::chrono::seconds(1));
mypool.PrintInfo();
std::this_thread::sleep_for(std::chrono::seconds(1));
mypool.PrintInfo();
std::this_thread::sleep_for(std::chrono::seconds(1));
mypool.PrintInfo();
std::this_thread::sleep_for(std::chrono::seconds(1));
mypool.PrintInfo();
}
}
int main()
{
tulun::Logger::setLogLevel(tulun::LOG_LEVEL::INFO);
//test_funb();
test_func();
return 0;
}
六、核心设计亮点与优化方向
6.1 设计亮点
- 原子变量保证线程安全 :
m_idleThreadSize、m_curThreadSize等使用std::atomic,避免锁竞争; - 超时机制避免永久阻塞 :任务队列的
wait_for和线程回收的超时判断,提升系统鲁棒性; - 移动语义减少拷贝:任务提交支持右值引用,降低大任务的拷贝开销;
- 降级策略:任务队列满时,直接在提交线程执行任务,避免任务丢失;
- 异步任务支持 :通过
packaged_task和future实现带返回值的任务提交。
6.2 可优化方向
- 线程回收机制 :当前使用
detach回收线程,可改为join并结合线程池销毁逻辑,更安全; - 任务优先级:扩展任务队列支持优先级,优先执行高优先级任务;
- 线程局部存储:为工作线程添加 TLS(线程局部存储),减少线程间资源竞争;
- 监控与统计:增加任务执行耗时、线程创建 / 回收次数等统计指标,便于性能调优;
- 异常捕获:工作线程执行任务时捕获异常,避免单个任务崩溃导致线程退出。
七、总结
缓存线程池是高并发场景下的高效线程管理方案,其核心价值在于用动态扩缩容平衡性能与资源消耗:
- 用线程安全的任务队列解耦任务提交与执行;
- 核心线程常驻,临时线程按需创建、超时回收;
- 原子变量和条件变量保证多线程下的状态同步;
- 降级策略和超时机制提升系统鲁棒性。
但缓存线程池并非 "银弹",在高负载、长时间任务场景下需谨慎使用,建议结合ThreadPoolExecutor 的设计思想,通过自定义参数实现更可控的线程池。