线程池
线程
-
创建方式
- 继承
Thread
类型 - 实现
Runnable
接口 - 实现
Callable
接口
- 继承
-
Java线程生命状态
- NEW ~新建
- RUNNABLE ~运行
- BLOCKED ~ 阻塞
- WAITING ~ 等待
- TIMED_WAITING ~超时等待
- TERMINATED ~终结
-
状态图
线程池
-
Why
- 频繁创建和销毁线程 会大大的降低系统效率
- 可以重用线程,减少线程的创建和销毁的开销,提高性能
- 提高响应速度,当任务到达是,不需要等待线程创建,就能立即执行
- 提高线程的可管理性, 线程是稀缺资源,不能无限制的创建,不仅会消耗系统资源,还会减低系统的稳定性。
-
How
-
创建线程
new ThreadPoolExecutor
/** * * @param corePoolSize 核心线程数 * @param maximumPoolSize 最大线程数 * @param keepAliveTime 线程池维护线程所允许的空闲时间。当线程池中的线程数量大于corePoolSize的时 * 候,如果这时没有新的任务提交,核心线程外的线程不会立即销毁,而是会等待,直到等待的时间超过了keepAliveTime; * @param unit keepAliveTime的单位; * @param workQueue 等待被执行的任务的阻塞队列,且任务必须实现Runable接口 * @param threadFactory Executors.defaultThreadFactory() 来创建线 * @param handler 线程池的饱和策略 */ public ThreadPoolExecutor(int corePoolSize, int maximumPoolSize, long keepAliveTime, TimeUnit unit, BlockingQueue<Runnable> workQueue, ThreadFactory threadFactory, RejectedExecutionHandler handler)
-
执行任务
-
execute(Runnable command)
执行没有返回值的任务
-
Future<?> submit(Runnable task)
执行有返回值的线程任务
-
-
阻塞队列 workQueue
-
ArrayBlockingQueue:
基于数组结构的有界阻塞队列,按FIFO排序任务
-
LinkedBlockingQuene
基于链表结构的阻塞队列,按FIFO排序任务,吞吐量通常要高于ArrayBlockingQuene
-
SynchronousQuene
一个不存储元素的阻塞队列,每个插入操作必须等到另一个线程调用移除操作,否则插入操作一直处于阻塞状态,吞吐量通常要高于LinkedBlockingQuene
用于
newCachedThreadPool
线程池 -
priorityBlockingQuene
具有优先级的无界阻塞队列
-
DelayedWorkQueue
DelayedWorkQueue是一个基于堆的数据结构,类似于DelayQueue和PriorityQueue,
用于
ScheduledThreadPoolExecutor
定时线程池里面
线程状态
-
RUNNING
线程池初始化状态是Running状态,能过接受新任务已经对已经接受的任务进行处理
-
SHUTDOWN
状态切换: 调用线程池的shutdown()接口时,线程池由RUNNING -> SHUTDOWN
状态说明:处于shutdown状态时,不接受新任务,但能处理已添加的任务。
-
STOP
状态切换: 调用线程池的shutdownNow()接口时,线程池由(RUNNING or SHUTDOWN ) -> STOP。
状态说明:处于stop 状态时,不接收新任务,不处理已添加的任务,并且会中断正在处理的任务。
-
TIDYING
状态切换:SHUTDOWN -> TIDYING 阻塞队列为空并且线程池中执行的任务也为空
STOP -> TIDYING 线程池中执行的任务为空
状态说明:所有任务已经终止
-
TERMINATED
状态切换:TIDYING ->TERMINATED
状态说明:线程池彻底终止,就变成TERMINATED状态
线程池原理
-
流程图
-
源码解析
public void execute(Runnable command) { if (command == null) throw new NullPointerException(); // clt记录着runState和workerCount int c = ctl.get(); // 1.判断当前线程数是否小于核心线程数, 如果小于,创建新的线程 if (workerCountOf(c) < corePoolSize) { if (addWorker(command, true)) return; c = ctl.get(); } // 2. 如当前线程池的状态时运行状态,就将任务添加到队列当中 if (isRunning(c) && workQueue.offer(command)) { // doubule check 检查线程池的状态, int recheck = ctl.get(); // 如果不是运行状态,将之前加入到队列中的任务删除,且执行拒接策列 if (! isRunning(recheck) && remove(command)) reject(command); // 如果工作线程数为0,启动一个新的非核心线程, else if (workerCountOf(recheck) == 0) addWorker(null, false); } // 【非RUNNING状态 or workerCount >= corePoolSize 且workQueue已满】,直接新增非核心线程,如果新增失败则拒接该任务 else if (!addWorker(command, false)) reject(command); }