JDK 线程池
线程池参数
在JDK的4种线程池之前, 先介绍一下线程池的几个参数
- corePoolSize 线程池的核心线程数量,
- maximumPoolSize 线程池的最大线程数量
- keepAliveTime 线程被回收的最大空闲时间
- keepAliveTime 的单位(ms、s、...)
- BlockingQueue 任务队列,存放任务
ThreadFactory 线程工厂
- RejectedExecutionHandler 线程池拒绝策略(当任务过多的时候,线程池拒绝任务的方式)
allowCoreThreadTimeOut 允许核心线程池被回收, 默认 false, so 默认情况下 核心线程并不会被回收掉.
JDK 提供的四种线程池介绍
newFixedThreadPool
固定线程池数量, 核心线程数 = 最大线程数
任务队列: LinkedBlockingQueue(Integer.MAX_VALUE) 无界队列
适用于同时处理固定任务数的场景.
public static ExecutorService newFixedThreadPool(int nThreads) {
// coreThreads = maxThreads
return new ThreadPoolExecutor(nThreads, nThreads,
0L, TimeUnit.MILLISECONDS,
new LinkedBlockingQueue<Runnable>());
}
newCachedThreadPool
核心线程数为0, 最大为 Integer.MAX_VALUE,也就是当任务足够多的时候, 可以无限增加线程.
任务队列: SynchronousQueue 默认传入参数 fair=false
, 即处理任务非公平.
适用于处理小任务
public static ExecutorService newCachedThreadPool() {
return new ThreadPoolExecutor(0, Integer.MAX_VALUE,
60L, TimeUnit.SECONDS,
new SynchronousQueue<Runnable>());
}
SynchronousQueue
public SynchronousQueue(boolean fair) {
// fair = true 则会按照FIFO先入先出的顺序执行
// fair = false 则优先取出最新添加的任务, 如果任务多的话,最先添加的任务反而执行不到
transferer = fair ? new TransferQueue<E>() : new TransferStack<E>();
}
newSingleThreadExecutor
单个线程的线程池
任务队列: LinkedBlockingQueue 同样是无界队列
适用于需要将任务按顺序执行的时候
public static ExecutorService newSingleThreadExecutor() {
// 核心线程数=最大线程数=1
return new FinalizableDelegatedExecutorService
(new ThreadPoolExecutor(1, 1,
0L, TimeUnit.MILLISECONDS,
new LinkedBlockingQueue<Runnable>()));
}
newScheduledThreadPool
固定核心线程数, 线程数量不会再增长, maximumPoolSize 这个参数对定时线程池没有作用.
任务队列: DelayedWorkQueue 无界队列, 这是 ScheduledThreadPoolExecutor 的一个内部类
适用于有延时 或者定时需求的场景
public ScheduledThreadPoolExecutor(int corePoolSize) {
super(corePoolSize, Integer.MAX_VALUE, 0, NANOSECONDS,
new DelayedWorkQueue());
}
线程拒绝策略
AbortPolicy
拒绝新任务,并且抛出异常, 默认的拒绝策略
public static class AbortPolicy implements RejectedExecutionHandler {
public AbortPolicy() { }
public void rejectedExecution(Runnable r, ThreadPoolExecutor e) {
// 直接抛出异常
throw new RejectedExecutionException("Task " + r.toString() +
" rejected from " +
e.toString());
}
}
CallerRunsPolicy
当拒绝任务的时候,由调用线程处理该任务.
public static class CallerRunsPolicy implements RejectedExecutionHandler {
public CallerRunsPolicy() { }
public void rejectedExecution(Runnable r, ThreadPoolExecutor e) {
// 如果线程池未停止
if (!e.isShutdown()) {
// 当前线程直接调用任务的run方法
r.run();
}
}
}
DiscardPolicy
拒绝新任务,静悄悄的将新任务丢弃,而不通知(太坑了吧), 具体看它的代码也是什么事情都没做, 还真的就直接丢弃任务了.
public static class DiscardPolicy implements RejectedExecutionHandler {
public DiscardPolicy() { }
public void rejectedExecution(Runnable r, ThreadPoolExecutor e) {
// 任务被拒绝后,啥事情都不干
}
}
DiscardOldestPolicy
当任务满时, 抛弃旧的未处理的任务, 然后重新执行 execute 方法(此过程会重复), 除非 线程池 停止运行, 这种情况任务将被丢弃.具体看代码
public static class DiscardOldestPolicy implements RejectedExecutionHandler {
public DiscardOldestPolicy() { }
public void rejectedExecution(Runnable r, ThreadPoolExecutor e) {
// 如果线程池停止, 直接丢弃任务,不做任何处理
if (!e.isShutdown()) {
// 丢弃一个任务队列中的任务
e.getQueue().poll();
// 重新执行被拒绝的任务, 如果再次被拒绝, 则会一直重复这个过程
e.execute(r);
}
}
}