通俗理解:
- 线程池:工厂
- 核心线程数:工厂正式工人数
- 最大线程数:正式工人人数+临时工人数
- 线程池中可容纳的最大任务数:正式工+临时工 加在一起 能做完的 工作量.
- 阻塞队列(任务队列):等待正式工完成的工作任务 也包含在正式工的工作量中
- 线程存活时间:临时工完成工作任务后间隔这么久没工作 就被辞退
- 丢弃策略:来了新的订单,但是此时工厂已经不能完成这个多的订单数量了,对新订单进行处理,比 如直接不接单,或者推荐给别的工厂之类的。
关系:
- 线程池中最大任务数量 = 最大线程数+阻塞队列初始长度
- 最大线程数=核心线程数初始值+核心线程以外的活跃线程数
拒绝策略生效条件: 最大线程数+阻塞队列长度<当前任务数
参数解释:
(1)corePoolSize:核心线程数,该参数说明了在线程池中保持核心线程的数量,由自己定义,刚创建线程池时,里面的核心线程数为0,随着任务的添加,达到核心线程数,执行完任务之后,线程池里面的核心线程数一直维持在设置的核心线程数。
(2)最大线程数(maximumPoolSize):该参数定义了一个线程池中最多能容纳多少个线程。当一个任务提交到线程池中时,如果线程数量达到了核心线程数,并且任务队列已满,不能再向任务队列中添加任务时,这时会检查任务是否达到了最大线程数,如果未达到,则创建新线程,执行任务,否则,执行拒绝策略。
(3)keepAliveTime:线程存活时间,线程池中大于核心线程数的那部分线程,即线程数总数量减去核心线程数的那部分线程,在执行完任务之后,在线程池中存活的时间,存活时间已超过这个值时就会关闭该线程。
(4)workQueue:任务队列,用来做缓冲作用,当提交到线程池中的任务核心线程数量不够用时,所有的核心线程都在执行任务,会将任务存到任务队列中,等待核心线程来执行。 workQueue+corePoolSize<=maximumPoolSize
(5)unit:keepAliveTime的单位,比如分钟,小时等
(6)handler:线程池拒绝任务的处理策略,丢弃策略。
丢弃策略:
- AbortPolicy - 丢弃任务,并抛出拒绝执行 RejectedExecutionException 异常信息。线程池默认的拒绝策略。必须处理好抛出的异常,否则会打断当前的执行流程,影响后续的任务执行。
- DiscardPolicy - 直接丢弃,其他啥都没有
- DiscardOldestPolicy - 当触发拒绝策略,只要线程池没有关闭的话,丢弃阻塞队列 workQueue 中最老的一个任务,并将新任务加入
- CallerRunsPolicy - 当触发拒绝策略,只要线程池没有关闭的话,则使用调用线程直接运行任务(指的时普通线程 不属于这个线程池里的线程)。一般并发比较小,性能要求不高,不允许失败。但是,由于调用者自己运行任务,如果任务提交速度过快,可能导致程序阻塞,性能效率上必然的损失较大
执行图解:
下图主要描述:核心线程用完以后,多余的线程任务会先放到任务队列中,当任务队列满了以后,再有任务才会去创建非核心线程来运行线程任务
代码实现:
1.工具类
package mms.shop.biz.config.threadPoolConfig;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.scheduling.annotation.EnableAsync;
import org.springframework.scheduling.concurrent.ThreadPoolTaskExecutor;
import org.springframework.scheduling.concurrent.ThreadPoolTaskScheduler;
import java.util.concurrent.RejectedExecutionHandler;
import java.util.concurrent.ThreadPoolExecutor;
@Configuration
@EnableAsync
public class ThreadPoolConfig {
private static final String Method="线程池:";
private static final Logger logger = LoggerFactory.getLogger(ThreadPoolConfig.class);
private int pool_size=1;
private int queue_capacity=