简单了解JAVA线程池

124 阅读2分钟

一起养成写作习惯!这是我参与「掘金日新计划 · 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:主线程中执行任务