# java 线程池有哪些核心参数,分别有什么作用
ThreadPoolExecutor threadPoolExecutor = new ThreadPoolExecutor( | |
8,//corePoolSize 线程池中的核心线程数量 | |
16,//maximumPoolSize | |
60,//keepAliveTime | |
TimeUnit.SECONDS,//keepAlive 的时间单位 | |
new ArrayBlockingQueue<Runnable>(1024),// 任务队列 | |
Executors.defaultThreadFactory(),// 线程工厂,用来创建线程,一般采用默认,也可自定义实现 | |
new ThreadPoolExecutor.CallerRunsPolicy()// 拒绝策略 (当 corePoolSize 正在执行 /workQueue 已满 / 线程数达 maximumPoolSize 需要拒绝新提交过来的事务) | |
); |
构造方法最多的是七个参数 3
# 线程池有哪些拒绝策略
JDK 提供了四种内置的拒绝策略
- AbortPolicy (默认): 丢弃任务并抛出 RejectedExecutionException 异常
- DiscardPolicy: 直接丢弃任务,不抛出异常,没有任何提示
- DiscardOldestPolicy: 丢弃任务队列中最靠前的任务,当前提交的任务不会丢弃
- CallerRunsPolicy: 交由任务的调用线程 (提交任务的线程) 来执行任务
除以上四种拒绝策略,还可以通过实现 RejectedExecutionHandler 接口,实现自定义的拒绝策略
# 说一说线程池的执行流程
# 线程池核心线程数该如何设置
- Ncpu = cpu 的核心数,Ucpu = cpu 的使用率 (在 0~1 之间)
- W = 线程等待时间,C = 线程计算时间
根据以上公式,可将任务分为 CPU 密集型和 IO 密集型
# CPU 密集型
CPU 密集型:线程数 = CPU 核心数 + 1
这种任务主要消耗 CPU 资源,比如加解密,压缩,计算等一系列需要大量耗费 CPU 资源的任务
比 CPU 核心数多出来的一个线程是为了防止线程偶发的缺页中断,或者其他原因导致的任务暂停而带来的影响。一旦任务暂停,CPU 就会处于空闲状态,而这种情况下多出来的一个线程就可以充分利用 CPU 的空闲时间.
# IO 密集型
线程数 = CPU 核心数 * 2
这种任务会有大部分时间进行 IO 操作,比如想 MySQL 数据库,文件读写,网络通信等任务,这类任务不会特别消耗 CPU 资源,但是 IO 操作比较耗时,会占用比较多的时间
线程在处理 IO 的时间段内不会占用 CPU, 这时就可以将 CPU 交出给其他线程使用,因此在 IO 密集型任务的应用中可以多配置一些线程
因此核心线程数配置的数量参考 CPU 的运行,合理配置线程数量就可以最大限度的利用 CPU
基本原则:
- 线程执行时间越多,就需要越少的线程
- 线程执行时间越少,就需要越多的线程