注意:本章主要参考自《大型分布式Java应用:基础与实践》和《大型网站技术架构:核心原理与案例分析》
1、选用的两个角度
- 高性能:将提交到线程池中的任务直接交给线程去处理(前提:线程数小于最大线程数),不入队
- 缓冲执行:希望提交到线程池的任务尽量被核心线程(corePoolSize)执行掉
2、高性能
- 队列:SynchronousQueue
- 最大线程数:一般设为Integer.MAX_VALUE(整数最大值),防止回绝任务
- 典型案例:newCachedThreadPool
- 尤其适合于执行耗时短的任务
注意:
- 设置好闲置失效时间,keepAliveTime,用于避免资源大量耗费
- 对于出现大量耗时长的任务,容易造成线程数迅速增加,这种情况要衡量使用该类线程池是否合适
3、缓冲执行
- 队列:LinkedBlockingQueue和ArrayBlockingQueue
- 典型案例:newFixedThreadPool(int threadSize)
注意:
- 使用该类线程池,最好使用LinkedBlockingQueue(无界队列),但是当大量并发任务的涌入,导致核心线程处理不过来,队列元素会大量增加,可能会报内存溢出
- 当然,对于上边这种情况的话,如果是ArrayBlockingQueue的话,如果设置得当,可以回绝一些任务,而不报内存溢出
4、线程数的确定
- 公式:启动线程数=[任务执行时间/(任务执行时间-IO等待时间)]*CPU核数
注意:
- 如果任务大都是CPU计算型任务,启动线程数=CPU核数+1
- 如果任务大多需要等待磁盘操作,网络响应,(IO密集型),启动线程数
- 可以参照公式估算,当然>CPU核数
- 2*cpu
- cpu/(1-0.8~0.9), eg 8核/(1-0.9)=80
总结:
一般使用线程池,按照如下顺序依次考虑(只有前者不满足场景需求,才考虑后者):
newCachedThreadPool-->newFixedThreadPool(int threadSize)-->ThreadPoolExecutor
- newCachedThreadPool不需要指定任何参数
- newFixedThreadPool需要指定线程池数(核心线程数==最大线程数)
- ThreadPoolExecutor需要指定核心线程数、最大线程数、闲置超时时间、队列、队列容量,甚至还有回绝策略和线程工厂
对于:newFixedThreadPool和ThreadPoolExecutor的核心数可以参照上述给出的公式进行估算。
分类:
Java并发包类源码解析
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· AI与.NET技术实操系列:基于图像分类模型对图像进行分类
· go语言实现终端里的倒计时
· 如何编写易于单元测试的代码
· 10年+ .NET Coder 心语,封装的思维:从隐藏、稳定开始理解其本质意义
· .NET Core 中如何实现缓存的预热?
· 25岁的心里话
· 闲置电脑爆改个人服务器(超详细) #公网映射 #Vmware虚拟网络编辑器
· 零经验选手,Compose 一天开发一款小游戏!
· 通过 API 将Deepseek响应流式内容输出到前端
· 因为Apifox不支持离线,我果断选择了Apipost!