Java线程池详解

线程池工作流程

线程池常用的阻塞队列

参数 描述
ArrayBlockingQueue 一个由数组结构组成的有界阻塞队列。
LinkedBlockingQueue 一个由链表结构组成的有界阻塞队列。常用
SynchronousQueue 一个不存储元素的阻塞队列,即直接提交给线程不保持它们。常用
PriorityBlockingQueue 一个支持优先级排序的无界阻塞队列。
DelayQueue 一个使用优先级队列实现的无界阻塞队列,只有在延迟期满时才能从中提取元素。
LinkedTransferQueue 一个由链表结构组成的无界阻塞队列。与SynchronousQueue类似,还含有非阻塞方法。
LinkedBlockingDeque 一个由链表结构组成的双向阻塞队列。

线程池的拒绝策略

参数 描述
AbortPolicy 拒绝并抛出异常。默认的
CallerRunsPolicy 重试提交当前的任务,即再次调用运行该任务的execute()方法。
DiscardOldestPolicy 抛弃队列头部(最旧)的一个任务,并执行当前任务。
DiscardPolicy 抛弃当前任务。

Executors创建线程池OOM的原因

FixedThreadPool

1
2
3
4
5
public static ExecutorService newFixedThreadPool(int nThreads) {
return new ThreadPoolExecutor(nThreads, nThreads,
0L, TimeUnit.MILLISECONDS,
new LinkedBlockingQueue<Runnable>());
}

SingleThreadPool

1
2
3
4
5
6
7
public static ExecutorService newSingleThreadExecutor() {
return new FinalizableDelegatedExecutorService
(new ThreadPoolExecutor(1, 1,
0L, TimeUnit.MILLISECONDS,
new LinkedBlockingQueue<Runnable>()));
}

以上两种线程池都采用了LinkedBlockingQueue,而LinkedBlockingQueue在初始化时的最大长度是Integer.MAX_VALUE

1
2
3
4
// LinkedBlockingQueue 初始化
public LinkedBlockingQueue() {
this(Integer.MAX_VALUE);
}

CachedThreadPool

1
2
3
4
5
public static ExecutorService newCachedThreadPool() {
return new ThreadPoolExecutor(0, Integer.MAX_VALUE,
60L, TimeUnit.SECONDS,
new SynchronousQueue<Runnable>());
}

这里线程池在初始化时,maximumPoolSize 参数用的是 Integer.MAX_VALUE,可能会创建大量的线程,导致发生OOM。