一、线程池的好处
(1)降低资源消耗。通过重复利用已创建的线程降低线程创建、销毁线程造成的消耗。
(2)提高响应速度。当任务到达时,任务可以不需要等到线程创建就能立即执行。
(3)提高线程的可管理性。线程是稀缺资源,如果入限制的创建,不仅会消耗系统资源,还会降低系统的稳定性,使用线程池可以进行统一的分配、调优和监控。
(4)可以有效控制最大并发线程数,提高系统的利用率,同时可以避免过多的资源竞争,避免阻塞。
二、线程池的核心参数
public ThreadPoolExecutor(int corePoolSize,
int maximumPoolSize,
long keepAliveTime,
TimeUnit unit,
BlockingQueue<Runnable> workQueue,
ThreadFactory threadFactory,
RejectedExecutionHandler handler) {
if (corePoolSize < 0 ||
maximumPoolSize <= 0 ||
maximumPoolSize < corePoolSize ||
keepAliveTime < 0)
throw new IllegalArgumentException();
if (workQueue == null || threadFactory == null || handler == null)
throw new NullPointerException();
this.acc = System.getSecurityManager() == null ?
null :
AccessController.getContext();
this.corePoolSize = corePoolSize;
this.maximumPoolSize = maximumPoolSize;
this.workQueue = workQueue;
this.keepAliveTime = unit.toNanos(keepAliveTime);
this.threadFactory = threadFactory;
this.handler = handler;
}
(1)corePoolSize: 线程池维护线程的最少数量 (core : 核心)
(2)maximumPoolSize: 线程池维护线程的最大数量
(3)keepAliveTime: 线程池维护线程所允许的空闲时间
(4)unit: 线程池维护线程所允许的空闲时间的单位
(5)workQueue: 线程池所使用的缓冲队列
(6)handler: 线程池对拒绝任务的处理策略
(7)threadFactory:线程工厂,用来创建线程(一般使用默认的线程工厂)
三、四大线程池的本质和特点
上面我们已经介绍了java线程的大六大核心参数,下面我们来介绍四大线程池的特点就比较简单了,因为四大线程池只不过是对ThreadPoolExecutor的六大核心参数进行了封装,我们来通过源码解析一下。
1.FixedThreadPool
通过源码我们可以很清晰的看出它的特点:
1.1 通过Exector的newFixedThreadPool静态方法来创建
1.2 线程数量固定的线程池
1.3 只有核心线程切并且不会被回收
1.4 当所有线程都处于活动状态时,新任务都会处于等待状态,直到有线程空闲出来
2.CachedThreadPool
2.1 通过Exector的newCachedThreadPool静态静态方法来创建
2.2 线程数量不定的线程池
2.3 只有非核心线程,最大线程数量为Integer.MAX_VALUE,可视为任意大
2.4 有超时机制,时长为60s,即超过60s的空闲线程就会被回收
2.5 当线程池中的线程都处于活动状态时,线程池会创建新的线程来处理新任务,否则就会利用空闲的线程来处理新任务。因此任何任务都会被立即执行
2.6 该线程池比较适合执行大量耗时较少的任务
3.ScheduledThreadPool
ScheduledThreadPool的源码稍微麻烦一点,但是它的原来还是没有变
3.1 通过Exector的newScheduledThreadPool静态方法来创建
3.2 核心线程数量是固定的,而非核心线程数不固定的,并且非核心线程有超时机制,只要处于闲置状态就会被立即回收
3.3 该线程池主要用于执行定时任务和具有固定周期的重复任务
4.SingleThreadPool
4.1 通过Exector的newSingleThreadPool静态方法来创建
4.2 只有一个核心线程,它确保所有的任务都在同一个线程中按顺序执行。因此在这些任务之间不需要处理线程同步的问题
其实四大线程池的原理非常简单,但是就是有些同学就是因为有了四大线程池的封装二忽视了对原理的学习,因此阿里巴巴急速从开发手册明确规定如下:
阿里巴巴开发规则
【强制】线程池不允许使用 Executors 去创建,而是通过 ThreadPoolExecutor 的方式,这样 的处理方式让写的同学更加明确线程池的运行规则,规避资源耗尽的风险。 说明:Executors 返回的线程池对象的弊端如下: 1)FixedThreadPool 和 SingleThreadPool: 允许的请求队列长度为 Integer.MAX_VALUE,可能会堆积大量的请求,从而导致 OOM。 2)CachedThreadPool 和 ScheduledThreadPool: 允许的创建线程数量为 Integer.MAX_VALUE,可能会创建大量的线程,从而导致 OOM。