目录
FixedThreadPool
CachedThreadPool
ScheduledThreadPool()
SingleThreadExecutor
本节我们来详解一下Executor框架的成员中的ThreadPoolExecutor
ThreadPoolExecutor 通常使用工厂 类 Executors 来 创 建。 Executors 可以 创 建 3 种 类 型的
ThreadPoolExecutor:SingleThreadExecutor、FixedThreadPool和CachedThreadPool。
本节就是详解这些类型的ThreadPoolExecutor
对Executor框架的了解可以看博主的上一篇文:
https://blog.csdn/m0_60264772/article/details/122778045
FixedThreadPool
特点:
- 核心线程数 == 最大线程数(没有救急线程),自然也无需超时时间
- 阻塞队列是无界的,可以放任意数量的任务
- 适用于任务量已知,相对耗时的任务
public static ExecutorService newFixedThreadPool(int threads) {
return new ThreadPoolExecutor(threads,threads,
0L, TimeUnit.MICROSECONDS,
new LinkedBlockingDeque<Runnable>());
}
CachedThreadPool
特点:
- 核心线程数是0,最大线程数是Integer.MAX_VALUE,救急线程的空闲时间为60s,意味着:
- 全部都是救急线程(60s后回收)
- 救急线程可以无限创建
- 队列采用了SynchronousQueue实现特点是,它没有容量,没有线程来取是放不进去的(一手交钱,一手交货)
- 整个线程线程数会根据任务量不断增长,没有上限,任务执行完毕,60s后释放线程
- 适合任务数比较密集,但每个任务执行时间较短的情况
public static ExecutorService newCachedThreadPool() {
return new ThreadPoolExecutor(0,
Integer.MAX_VALUE,
60L,
TimeUnit.SECONDS,
new SynchronousQueue<>());
}
ScheduledThreadPool()
定长线程池:
- 支持定时及周期性任务执行
-
ExecutorService scheduledThreadPool = Executors.newScheduledThreadPool(int corePoolSize);
public static ScheduledExecutorService newScheduledThreadPool(int corePoolSize) { return new ScheduledThreadPoolExecutor(corePoolSize); } //ScheduledThreadPoolExecutor(): public ScheduledThreadPoolExecutor(int corePoolSize) { super(corePoolSize, Integer.MAX_VALUE, DEFAULT_KEEPALIVE_MILLIS, MILLISECONDS, new DelayedWorkQueue()); }
SingleThreadExecutor
特点:
- 线程数始终为1,不能修改。希望多个任务排队执行。任务数多于 1 时,会放入无界队列排队。 任务执行完毕,这唯一的线程也不会被释放
public static ExecutorService newSingleThreadExecutor() {
return new FinalizableDelegatedExecutorService
(new ThreadPoolExecutor(1, 1,
0L, TimeUnit.MILLISECONDS,
new LinkedBlockingQueue<Runnable>()));
}
有同学可能就会有疑问了,那么new FixedThreadPool(1)参数设置为1不是就一样了吗,实际上还是有区别的:
- 自己创建一个单线程串行执行任务,如果任务执行失败而终止那么没有任何补救措施,而newSingleThreadExecutor线程池还会新建一个线程,保证池的正常工作
- Executors.newSingleThreadExecutor() 线程个数始终为1,不能修改(FinalizableDelegatedExecutorService 应用的是装饰器模式,只对外暴露了 ExecutorService 接口,因此不能调用 ThreadPoolExecutor 中特有的方法)
- 和Executors.newFixedThreadPool(1) 初始时为1时的区别:Executors.newFixedThreadPool(1) 初始时为1,以后还可以修改,对外暴露的是 ThreadPoolExecutor 对象,可以强转后调用 setCorePoolSize 等方法进行修改
Executors 返回线程池对象的弊端如下
FixedThreadPool 和 SingleThreadExecutor : 允许请求的队列长度为 Integer.MAX_VALUE (无界阻塞队列),可能堆积大量的请求,从而导致 OOM。
CachedThreadPool 和 ScheduledThreadPool : 允许创建的线程数量为 Integer.MAX_VALUE ,可能会创建大量线程,从而导致 OOM。
建议使用ThreadPoolExecutor
来创建线程
避免上面的措施 : 使用有界队列,控制线程创建数量。
除了避免 OOM 的原因之外,不推荐使用 Executors提供的两种快捷的线程池的原因还有:
实际使用中需要根据自己机器的性能、业务场景来手动配置线程池的参数比如核心线程数、使用的任务队列、饱和策略等等。
我们应该显示地给我们的线程池命名,这样有助于我们定位问题。
更多推荐
常见四种线程池
发布评论