什么是线程池
在我们的实际开发中,通常使用线程池创建线程资源。
而线程池本质上是一种池化技术,利用资源复用的思想,复用线程资源。
为什么使用线程池
那么,我们为什么要使用线程池呢?主要有以下两点原因:
- 首先,使用线程池可以避免频繁创建和销毁线程所带来的性能开销。因为线程的创建会涉及到
CPU
上下文的切换以及内存的分配。 - 其次,我们可以通过线程池参数控制线程的数量,避免无休止的创建线程带来的资源利用率过高的问题,从而起到资源保护的作用。
线程池的状态
在我们使用线程池时,一共涉及 5
种状态,其中包括:
-
RUNNING
:能接受新提交的任务,并且也能处理阻塞队列中的任务; -
SHUTDOWN
:关闭状态,不再接受新提交的任务,但却可以继续处理阻塞队列中已保存的任务。在线程池处于RUNNING
状态时,调用shutdown()
方法会使线程池进入到该状态。(finalize()
方法在执行过程中也会调用shutdown()
方法进入该状态); -
STOP
:不能接受新任务,也不处理队列中的任务,会中断正在处理任务的线程。在线程池处于RUNNING
或SHUTDOWN
状态时,调用shutdownNow()
方法会使线程池进入到该状态; -
TIDYING
:如果所有的任务都已终止了,workerCount
(有效线程数) 为0
,线程池进入该状态后会调用terminated()
方法进入TERMINATED
状态。 -
TERMINATED
:在terminated()
方法执行完后进入该状态,默认terminated()
方法中什么也没有做。进入TERMINATED的条件如下:- 线程池不是
RUNNING
状态; - 线程池状态不是
TIDYING
状态或TERMINATED
状态; - 如果线程池状态是
SHUTDOWN
并且workerQueue
为空; workerCount
为0
;- 设置
TIDYING
状态成功。
- 线程池不是
线程池的分析及源码
核心属性
private final AtomicInteger ctl = new AtomicInteger(ctlOf(RUNNING, 0));
// COUNT_BITS = 32 - 3 = 29
private static final int COUNT_BITS = Integer.SIZE - 3;
// 工作线程的最大个数
// 00100000 00000000 00000000 00000000 - 1
// 000111111111111111111111111111111
private static final int CAPACITY = (1 << COUNT_BITS) - 1;
// runState is stored in the high-order bits
private static final int RUNNING = -1 << COUNT_BITS;
private static final int SHUTDOWN = 0 << COUNT_BITS;
private static final int STOP = 1 << COUNT_BITS;
private static final int TIDYING = 2 << COUNT_BITS;
private static final int TERMINATED = 3 << COUNT_BITS;
其中 ctl
属性维护着线程池的两个重要内容:
- 高
3
位维护着线程池的状态; - 低
29
位维护着工作线程个数;
ctl 相关方法
// Packing and unpacking ctl
// 获取线程池状态
private static int runStateOf(int c) { return c & ~CAPACITY; }
// 获取工作线程数
private static int workerCountOf(int c) { return c & CAPACITY; }
// 获取运行状态和工作线程数的值
private static int ctlOf(int rs, int wc) { return rs | wc; }
ThreadPoolExecutor 构造方法
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;
}
可以看出,在 ThreadPoolExecutor
的有参构造器中一共有 6
个参数: