前言
真实高并发场景下,项目一般不会直接使用 Thread 类创建线程,而是使用线程池来创建并管理线程。对于程序员来说,学好线程池对于并发编程是非常重要的。
为什么要使用线程池
主要有以下三方面的原因:
-
频繁的创建/销毁线程需要消耗系统资源,线程需要重新被cpu从就绪到运行状态调度,需要发生cpu的上下文切换,效率非常低。 -
并发数量过多,可能会导致资源消耗过多,从而造成服务器崩溃。(主要原因) -
可以对线程做统一管理。
ThreadPoolExecutor 参数
-
int corePoolSize: 核心线程数 -
int maximumPoolSize: 最大线程数 -
long keepAliveTime: 超出corePoolSize后创建的线程的存活时间 -
TimeUnit unit: keepAliveTime的时间单位 -
BlockingQueue workQueue: 阻塞队列,维护着等待执行的Runnable任务对象 -
ThreadFactory threadFactory: 创建线程的线程工厂
![alt](https://i-blog.csdnimg.cn/blog_migrate/63f31833a7f813f86d982584d0a99fd6.png)
执行过程 :
-
当线程数小于核心线程数时,创建线程。 -
当线程数大于等于核心线程数,且任务队列未满时,将任务放入任务队列。 -
当线程数大于等于核心线程数,且任务队列已满时:
-
若线程数小于最大线程数,创建线程 -
若线程数等于最大线程数,执行拒绝策略
拒绝策略
线程池提供了4种拒绝策略,分别如下:
-
AbortPolicy:直接抛出异常,这也是默认的策略。。 -
CallerRunsPolicy:使用调用者所在的线程来执行任务。 -
DiscardOldestPolicy:丢弃队列中最靠前的任务并执行当前任务。 -
DiscardPolicy:直接丢弃当前任务。
如何设置线程数
合理地设置核心线程数和最大线程数可以优化线程池的性能和响应时间。建议如下:
-
核心线程数 = CPU核心数 + 1 -
最大线程数 = 核心线程数 * 2 -
如果任务执行时间较长,可以适当增加最大线程数,以避免任务堆积在队列中无法及时处理
总结
本文详解了线程池的概念以及执行流程,在生产过程中如何合理的使用还需要线上的验证,希望本文对大家有帮助!
本文由 mdnice 多平台发布