一起养成写作习惯!这是我参与「掘金日新计划 · 4 月更文挑战」的第6天,点击查看活动详情。
线程池是一个重要的知识点,谈到线程池时,有的人一脸懵逼,有的人长篇阔论,差别在哪?在于知识的深度。。
问题:
1、线程池各个参数的作用,简单阐述线程池工作流程。
2、常见的线程池有哪些,分别适用于什么场景?
3、使用无界队列的线程会导致内存OOM吗?
JAVA 线程池的概念
管理线程的池子,使用线程池,有如下优点:
(1)降低线程创建和销毁线程造成的开销
(2)提高响应速度。任务到达时,相对于手工创建一个线程,直接从线程池中拿线程,速度肯定快很多
(3)提高线程可管理性。线程是稀缺资源,如果无限制地创建,不仅会消耗系统资源,还会降低系统稳定性,使用线程池可以进行统一分配、调优和监控。
Java线程池创建
无论是创建何种类型线程池(FixedThreadPool、CachedThreadPool…),均会调用ThreadPoolExecutor构造函数,下面详细解读各个参数的作用
publicThreadPoolExecutor(int corePoolSize,int maximumPoolSize,long keepAliveTime,TimeUnit unit,BlockingQueue workQueue){
this(corePoolSize, maximumPoolSize, keepAliveTime, unit, workQueue,Executors.defaultThreadFactory(), defaultHandler);
}
corePoolSize:核心线程最大数量,通俗点来讲就是,线程池中常驻线程的最大数量
maximumPoolSize:线程池中运行最大线程数(包括核心线程和非核心线程)
keepAliveTime:线程池中空闲线程(仅适用于非核心线程)所能存活的最长时间
unit:存活时间单位,与keepAliveTime搭配使用
workQueue:存放任务的阻塞队列
handler:线程池饱和策略
线程池执行流程
当提交一个新任务,线程池的处理流程如下:
判断线程池中核心线程数是否已达阈值corePoolSize,若否,则创建一个新核心线程执行任务
若核心线程数已达阈值corePoolSize,判断阻塞队列workQueue是否已满,若未满,则将新任务添加进阻塞队列
若满,再判断,线程池中线程数是否达到阈值maximumPoolSize,若否,则新建一个非核心线程执行任务。若达到阈值,则执行线程池饱和策略。
线程池饱和策略分为一下几种:
AbortPolicy:直接抛出一个异常,默认策略
DiscardPolicy: 直接丢弃任务
DiscardOldestPolicy:抛弃下一个将要被执行的任务(最旧任务)
CallerRunsPolicy:主线程中执行任务