1. 背景及优势
1.1 背景
在日常的业务(如:抢票,购物等)开发中,为了提高并发,经常会选择多线程的方式。当有多个线程在操作时,如果系统只有一个CPU,则它根本不可能真正同时进行一个以上的线程,它只能把CPU运行时间划分成若干个时间段,再将时间 段分配给各个线程执行,在一个时间段的线程代码运行时,其它线程处于挂起状。.这种方式我们称之为并发(Concurrent)。
多线程的引入虽然使得资源利用率更好、程序设计更简单、程序响应更快,但它同时也意味着底层设计更复杂、不可避免的上下文切换的开销以及先关资源消耗的增加。没有线程池的概念时,我们通常调用new Thread()创建野线程,这样的线程缺乏管理而且可以无限制创建,他们之间相互竞争,会导致过多占用系统资源导致系统瘫痪。因此线程池应运而生。
1.2 优点
核心的思想就是把宝贵的线程资源放到一个池子中,每次使用都从里面获取,用完之后又放回池子供其他人使用。因此他的优势在于重用存在的线程,减少对象创建、消亡的开销,性能佳可有效控制最大并发线程数,提高系统资源的使用率,同时避免过多资源竞争,避免堵塞,提供定时执行、定期执行、单线程、并发数控制等功能。
2. 线程池框架 Executor
2.1 线程池的状态
在线程池类ThreadPoolExecutor类中定义了线程的状态常量(删除了部分注释):
/**
* The main pool control state, ctl, is an atomic integer packing
* two conceptual fields
* workerCount, indicating the effective number of threads
* runState, indicating whether running, shutting down etc
* RUNNING: Accept new tasks and process queued tasks
* SHUTDOWN: Don't accept new tasks, but process queued tasks
* STOP: Don't accept new tasks, don't process queued tasks,
* and interrupt in-progress tasks
* TIDYING: All tasks have terminated, workerCount is zero,
* the thread transitioning to state TIDYING
* will run the terminated() hook method
* TERMINATED: terminated() has completed
*
* The numerical order among these values matters, to allow
* ordered comparisons. The runState monotonically increases over
* time, but need not hit each state. The transitions are:
*
* RUNNING -> SHUTDOWN
* On invocation of shutdown(), perhaps implicitly in finalize()
* (RUNNING or SHUTDOWN) -> STOP
* On invocation of shutdownNow()
* SHUTDOWN -> TIDYING
* When both queue and pool are empty
* STOP -> TIDYING
* When pool is empty
* TIDYING -> TERMINATED
* When the terminated() hook method has completed
*/
private final AtomicInteger ctl = new AtomicInteger(ctlOf(RUNNING, 0));
private static final int COUNT_BITS = Integer.SIZE - 3;
private static final int CAPACITY = (1 << COUNT_BITS) - 1;
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;
有上可知ThreadPoolExecutor的ctl字段高三位保存了runState(运行状态),低29位保存了workerCount(工作线程个数)。线程池有以下五种状态:
-
RUNNING
(1)状态说明:运行状态,指可以接受任务执行队列里的任务线程池的初始化状态是RUNNING。换句话说,线程池被一旦被创建,就处于RUNNING状态,并且线程池中的任务数为0。
(2)状态切换:线程池的初始化状态是RUNNING。换句话说,线程池被一旦被创建,就处于RUNNING状态,并且线程池中的任务数为0! -
SHUTDOWN
(1) 状态说明:线程池处在SHUTDOWN状态时,不接收新任务,但能处理已添加的任务。
(2) 状态切换