学习目标
-
线程池的作用
-
jdk给我们提供了哪几种常用线程池
-
线程池有哪几大核心参数
-
线程池的拒绝策略有哪些
-
线程中阻塞队列的作用
-
线程池的工作流程
-
线程池的设计思维
-
线程池中的阻塞队列如果用默认的,会有哪些问题
-
线程池的工作状态有哪些
-
线程池中核心线程数量大小怎么设置?
第1章 线程池简介
1.1 线程的问题
-
线程执行完run发放自动被销毁了,且任务与线程绑定在了一起,所以当任务多的时候,会频繁的创建和销毁线程,这给我们CPU和内存带来了很大的开销。
-
线程一多了,无法实现统一管理。
1.2 线程池的概念及作用
-
他是池化技术的一种应用
-
他实现了线程的重复利用
-
实现了对线程资源的管理控制
1.3 常见线程池
-
newFixedThreadPool:该方法返回一个固定数量的线程池,线程数不变,当有一个任务提交时,若线程池中空闲,则立即执行,若没有,则会被暂缓在一个任务队列中,等待有空闲的线程去执行。
-
newSingleThreadExecutor: 创建一个线程的线程池,若空闲则执行,若没有空闲线程则暂缓在任务队列中。
-
newCachedThreadPool:返回一个可根据实际情况调整线程个数的线程池,不限制最大线程数量,若用空闲的线程则执行任务,若无任务则不创建线程。并且每一个空闲线程会在60秒后自动回收
-
newScheduledThreadPool: 创建一个可以指定线程的数量的线程池,但是这个线程池还带有延迟和周期性执行任务的功能,类似定时器。
-
newWorkStealingPool:适合使用在很耗时的操作,但是newWorkStealingPool不是ThreadPoolExecutor的扩展,它是新的线程池类ForkJoinPool的扩展,但是都是在统一的一个Executors类中实现,由于能够合理的使用CPU进行对任务操作(并行操作),所以适合使用在很耗时的任务中
第2章 线程池原理分析
2.1 初始化
我们先看下初始化5个参数
public ThreadPoolExecutor(int corePoolSize,
int maximumPoolSize,
long keepAliveTime,
TimeUnit unit,
BlockingQueue<Runnable> workQueue) {
this(corePoolSize, maximumPoolSize, keepAliveTime, unit, workQueue,
Executors.defaultThreadFactory(), defaultHandler);
}
public ThreadPoolExecutor(int corePoolSize, //主线程数
int maximumPoolSize, //最大线程数
long keepAliveTime, //线程存活时间 (除主线程外,其他的线程在没有任务执行的时候需要回收,多久后回收)
TimeUnit unit, //存活时间的时间单位
BlockingQueue<Runnable> workQueue, //阻塞队列,我们需要执行的task都在该队列
ThreadFactory threadFactory, //生成thread的工厂
RejectedExecutionHandler handler) { //拒绝饱和策略,当队列满了并且线程个数达到 maximunPoolSize 后采取的策略
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