线程池使用注意事项(正确使用线程池的姿势)
线程池使用注意事项(正确使用线程池的姿势)关于线程池大小的设置:1 核心线程数 2 最大线程数 3 线程池中空闲线程等待工作的超时时间 4 阻塞队列类型(有界或者无界)5 拒绝策略为什么使用线程池为了提高资源利用率,复用线程,减少线程的创建与销毁的开销。有经验的开发者,线程池一般都会选择创建固定大小。更有经验的会自己手动设置线程池的相关参数。
背景
因为最近给同事们灌输了尽量让接口里面的方法异步化,尽量使用线程池来处理任务。所以同事们都把自己写得比较耗时的方法(一般都是一个方法里面要多次与数据库交互)改造成多线程的方式,大大的缩减了接口的响应时间。分享一下相关知识,希望能帮到对线程池不太熟悉的同学。
线程池流程
流程图
为什么使用线程池
为了提高资源利用率,复用线程,减少线程的创建与销毁的开销。
有经验的开发者,线程池一般都会选择创建固定大小。更有经验的会自己手动设置线程池的相关参数。
1 核心线程数 2 最大线程数 3 线程池中空闲线程等待工作的超时时间 4 阻塞队列类型(有界或者无界)5 拒绝策略
关于线程池大小的设置:
工作中线程数量设置多少合适?(一般计算密集型线程池大小设置为CPU个数,IO密集型的任务线程池大小设置为CPU个数的2N 1)。 最好的方式是通过压力测试来实验。
任务过多的处理
任务超出了线程总数后怎么拒绝?
系统给出的四种策略:
1 直接丢弃(就像和女朋友没有告别的分手)
2 丢弃抛出异常(给女朋友分手找个理由,也是默认的拒绝策略)
3 丢弃最早的任务(喜新厌旧)
4 由调用线程(提交任务的线程)直接执行此任务
可能存在的风险:任务会交给上层线程(主线程)执行,导致上层线程既要处理其他任务,又要忙碌处理线程池的源源不断的任务,导致悬挂,进而导致线上故障。
自定义的拒绝策略:
将任务信息放入消息队列中 (不放弃任务一个任务)
核心线程会被回收吗
默认不会,如果设置成会的话,超过keepAliveTime后一样会像非核心线程一样被回收,但是这样就失去了线程池设计的初衷,即为了复用线程。
写在最后
即便使用池化技术,也只是提高了线程池内的线程利用率,但在高并发的业务场景中,池化技术一样会带来性能和资源开销的问题。如果我们使用消息组件来执行异步业务,则可以在性能和资源两者之间做一个很好的平衡.