如何合理配置线程池的大小
如何合理配置线程池的大小
1. 理论背景
一般需要根据任务的类型来配置线程池大小:
如果是CPU密集型任务,就需要尽量压榨CPU,应配置尽可能小的线程,参考值可以设为 NCPU+1
如果是IO密集型任务,因为IO操作不占用CPU,不要让CPU闲下来,应加大线程数量,参考值可以设置为2NCPU+1
当然,这只是一个参考值,具体的设置还需要根据实际情况进行调整,比如可以先将线程池大小设置为参考值,再观察任务运行情况和系统负载、资源利用率来进行适当调整。
2. 什么是io秘籍和CPU 秘籍
io密集型(要减少请求数量或请求大小)
- 数据库操作
- 网络请求操作
cpu 密集型
- 程序计算
3. 实例测试
在做数据清理时,需要查询数据库,做数据清洗完成后,再保存到数据库
测试逻辑步骤
- 查询出总记录数
- 每100条记录划分一组在线程池中操作
我win 核心线程为4
不使用多线程的时候,每分钟执行500条
改用多线程后
线程数 | 每分钟执行条数 | 5分钟执行条数 |
---|---|---|
核心线程数5,最大线程数10 | 4400(初次线程停顿条数1100) | |
核心线程数10,最大线程数20 | 8400(初次线程停顿条数2100) | |
核心线程数20,最大线程数40 | 12300(初次线程停顿条数4100) | |
核心线程数30,最大线程数60 | 18300(初次线程停顿条数6100) | |
核心线程数40,最大线程数80 | 24300(初次线程停顿条数8100) | |
核心线程数50,最大线程数100 | 26716(初次线程停顿条数9994) | |
核心线程数60,最大线程数120 | 27300(初次线程停顿条数9854) | |
核心线程数70,最大线程数140 | 19942(初次线程停顿条数9747) | |
核心线程数80,最大线程数160 | 29770(初次线程停顿条数9747) |
初次线程停顿条数:清理到数据库中的数据从0开始到一个稳定的数(线程池差不多同一时间执行完毕的,过渡到其他线程)
该实验建立在每分钟的基础上。每个线程执行时间15-20s左右。那1分钟执行3-4次。所以误差比较明显
3.1 实验分析
实现出的结果显示2n+1 的结论。线程数量还远不能达到最佳线程。继续查阅资料发现一个估算公式
最佳线程数目 = ((线程等待时间+线程CPU时间)/线程CPU时间 )* CPU数目
比如平均每个线程 CPU 运行时间为 0.5s,而线程等待时间(非 CPU 运行时间,比如 IO)为 1.5s,CPU 核心数为 8,那么根据上面这个公式估算得到:((0.5+1.5)/0.5)*8=32。这个公式进一步转化为:
最佳线程数目 = (线程等待时间与线程CPU时间之比 + 1)* CPU数目
线程等待时间所占比例越高,需要越多线程。线程 CPU 时间所占比例越高,需要越少线程。
一个系统最快的部分是 CPU,所以决定一个系统吞吐量上限的是 CPU。增强 CPU 处理能力,可以提高系统吞吐量上限。但根据短板效应,真实的系统吞吐量并不能单纯根据 CPU 来计算。那要提高系统吞吐量,就需要从 “系统短板”(比如网络延迟、IO)着手:
- 尽量提高短板操作的并行化比率,比如多线程下载技术
- 增强短板能力,比如用 NIO 替代 IO