前言
在面试的过程中,总会说:谈谈你对线程池的理解。
什么是线程池?
线程池有什么优势?
如何创建线程池?
线程池的参数配置是什么?
常用线程分类有什么?
为此,做一个总结。巩固我那薄弱的知识。
什么是线程池?
存放线程的一个空间?区域?池子。可以说线程池的内部维护了若干的线程。这些线程等待着任务来进行执行。就如同一个共享单车基地一样。维护了很多的单车,等你有人来使用。对于线程池,如果有任务就分配一个线程池中的线程来执行,如果线程池中的线程用完了就把这些任务反放在工作队列中,放对列满执行了再,或者没有(不是真的没有只是为空)队列来方,直接创建一个新线程来执行。
同样是创建线程,线程池创建有什么优势呢?
线程池的优势?
1.降低资源的消耗:他可以重复利用已经创建过的线程来执行任务,减少多次创建和销毁的消耗
2.提高相应的速度,这里的速度不是线程创建的速度,而是从原来的先创建线程,然后再执行任务,变成了统一创建好了线程,下次任务来了之后直接执行。省去了每次创建的时间消耗
3.提高线程的可管理性:使用线程池,可以统一的分配、调优、和监控。
那么我们应该如何创建线程池呢?
如何创建线程池
我们通过ThreadPooExecutor的构造方法来创建线程池
这里就需要理解这七个参数分别是什么
ThreadPoolExecutor threadPoolExecutor = new ThreadPoolExecutor(0, 0, 0, null, null, null, null);
线程池的参数配置
1,核心线程数量
2,线程池最大线程数量
3,线程池的非核心线程的存活时间
4,时间单位
5,工作队列。
6,创建线程的线程工厂
7,拒绝策略
1.线程池核心线程数量:
可以理解成线程池最小的线程数量,核心线程数量不会被回收,而且核心线程在创建任务的时候立刻被创建并且执行任务。
2.线程允许创建的最大线程数量(这个最大线程数量是包含了核心线程数量的)当任务大于核心线程数量,且工作队列已满,那么会创建非核心线程来执行任务。
3.线程池的非核心线程存活时间(见名知意)
4.是上面那个存活时间的时间单位
5.工作队列,BolckingQueue,一个阻塞工作队列,用来存储等待执行的任务。
阻塞队列的实现机制是生产者消费者模型,一个线程负责存储任务,一个线程负责取出任务。
常用的BlokingQueue
ArrayBlockingQueue:这是一个有界队列,基于数组实现,维护了一个定长数组,按照先进先出排序。
LinkedBolckingQueue:这是一个无界队列,容量可以设置,如果不设置的话是Interger.MAX_VALUE。这个的吞吐量一般比ArrayBlockingQueue高。
(FixedThreadPool、SingleThreadExecutor线程使用LinkedBolkingQueue队列。)
LiknkedBolckingQueue是一个无界队列,在这种队列情况下,最大线程数是一个无效参数,但是在设计的时候依然设计了最大线程数的配置。
DelayedWorkQueue是一个基于堆结构的延迟队列。底层基于数组实现。初始容量是16,他的排序是按照指定的延迟时间从小到大排序的。
ScheduledThreadPool使用了这个队列
PriorityBlokingQueue(优先任务队列)
按照用户的需求来设置优先等级,调整任务的执行顺序。
SynchronousQueue(同步队列)
他不存储元素的阻塞队列(内部没有保存元素的数据结构)。使用SynchronousQueue队列,提交的任务不会被保存,总是立刻被执行。
6:创建线程的线程工厂:
一般使用默认的线程工厂,如果有一些自己的设计,比如改变线程的名称,那么可以自定义一个线程工厂。
7:拒绝策略
默认策略是丢弃任务并且抛出异常
还有丢弃任务
还有丢弃队列中的末尾任务(最旧的任务,也就是最早进入队列的任务)
由有调用线程处理该任务
线程池的运行过程:
提交任务:核心线程池是否已满:如果没有满就执行创建核心线程并且执行任务。如果核心线程池满了,就放入队列中,如果队列满了,就去判断线程池中的线程是否已经超过最大线程数。如果是就按照拒绝策略处理。没有满就创建非核心线程来执行任务。
4.常见线程池有哪些以及使用场景?
FixedThreadPool
线程数固定的线程池:
核心线程数和最大线程数一致
非核心线程的空闲存活时间即KeepALiveTime为0
阻塞队列为无界队列LinkedBlockingQueue
工作机制:
a.提交线程任务
b.如果线程数少于核心数创建核心线程执行任务,如果等于核心线程,把任务添加到LinkedBlckinghQueue阻塞队列,如果线程执行完,就去阻塞对了取任务,继续执行。
适用于处理CPU密集型任务,确保CPU在长期被工作线程使用的情况下,尽可能少的的分配xianc
CachedThreadPool(可缓存线程池)
线程数根据任务动态调整的线程池
核心线程数0,最大线程数是Interger.MAX_VALUE,工作队列是synChronousQueue同步队列。非核心线程空闲存活时间为60秒
工作机制
提价线程任务,因为核心数为-0,所以任务之间加入到SynchronousQueue工作队列中,判断是否有空闲线程,如果有就取出去执行,如果没有就新建一个。
SingleThreadExecutor 单线程化的线程池
线程池参数: 核心线程数1,最大线程数1,阻塞线程是LInkedBlockQueue,f非核心线程数存活为0秒
适用于 串行执行任务的场景,将任务按顺序执行。
ScheduledTheadPool
能实现定时、周期性任务的线程池
线程池参数:
最大为Integer。MAX_VALUE
阻塞队列是DelayedWorkQueue
keepAliveTime为0
执行周期性任务,并且需要限制线程数量的需求场景。
线程 池的状态
线程池的状态:Running、shutdown、stop、tidying、terminated
rounning:运行状态,线程池一旦被创建就,处于running状态。并且线程池中的任务为0;
shutdown,关闭状态,不会接受新任务,但会处理工作队列中的任务。(使用shutdown()方法进入shutdown状态)
stop:停止状态,该状态的线程不会接收新任务,也不会处理阻塞队列的中如,而且会中断正在运行的任务。
terminated:terminated表示线程池彻底终止