前言
线程池是java面试被问的高频问题之一,线程池的工作原理、自定义线程池的参数含义、JUC包常用线程池等等,在此整理总结,供大家参考学习。
一、为什么要使用线程池
线程是稀缺资源,如果被无限制的创建,不仅会消耗系统资源,还会降低系统的稳定性,合理的使用线程池对线程进行统一分配、调优和监控。
使用线程池的优点:
1、降低系统资源消耗,通过重用已存在的线程,降低线程创建和销毁造成的消耗
2、提高系统响应速度,当有任务到达时,通过复用已存在的线程,无需等待新线程的创建便能立即执行
3、方便线程并发数的管控。因为线程若是无限制的创建,可能会导致内存占用过多而产生OOM,并且会造成cpu过度切换
4、提供更强大的功能,提供延时、定时线程池
二、线程池的主要参数
三、线程池的工作流程
执行流程图
步骤一: 判断正在运行的线程数是否小于corePoolSize(核心线程数),小于则立马创建线程运行该任务。
步骤二: 正在运行的线程数大于或等于corePoolSize(核心线程数),那么将该任务放入队列。
步骤三: 如果队列已满,且正在运行的线程数是否小于maximumPoolSize(最大线程数),那么创建临时线程(非核心线程)立刻运行该任务。
步骤四: 如果队列已满,且正在运行的线程数大于或等于maximumPoolSize(最大线程数),那么线程池会执行拒绝策略的方法。
四、Java提供的常用线程池
FixedThreadPool: 创建一个固定大小的线程池,因为采用无界的阻塞队列,所以实际线程数量永远不会改变,适用于负载较重的场景,对当前线程数量进行限制。(保证线程数可控,不会造成线程过多,导致系统负载更为严重)。
ScheduleThreadPool: 适用于执行延时或者周期性任务。
CacheedThreadPool: 用来创建一个可以无限扩大的线程池,适用于负载较轻的场景,执行短期异步任务。(可以使得任务快速得到执行,因为任务时间执行短,可以很快结束,也不会造成cpu过度切换)。
SingleThreadExcutor: 创建一个单线程的线程池,适用于需要保证顺序执行各个任务。