1.为什么要使用线程池
当然是大量的实际业务场景中发现前三种线程的初始化方式不好用呗,所以才有了对线程进行管理的这样一个对象的抽象封装也就是线程池
具体线程池好处在哪里呢?
这里我就不多说了,前人总结的经验,有时间的可以瞧瞧 百度百科
https://baike.baidu.com/item/%E7%BA%BF%E7%A8%8B%E6%B1%A0/4745661?fr=aladdin
主要概括起来就以下几点
2.线程池初始化方式及七大参数
知道为啥要使用这玩意了,下面聊聊咋用
首先,为啥要学这玩意,1.应付面试 2.自己用
应付面试嘛,就要稍微了解多一点,来,看故事与面试题
我们创建线程池一般根据需求会选择下面四种创建线程池方式中的一种,那么具体使用哪一种呢?根据具体业务场景选择不同
- newSingleThreadExecutor 创建一个单线程化的线程池,它只会用唯一的工作线程来执行任务,保证所有任务按照指定顺序(FIFO, LIFO, 优先级)执行。
- newFixedThreadPool 创建一个定长线程池,可控制线程最大并发数,超出的线程会在队列中等待。
- newScheduledThreadPool 创建一个可定期或者延时执行任务的定长线程池,支持定时及周期性任务执行。
- newCachedThreadPool 创建一个可缓存线程池,如果线程池长度超过处理需要,可灵活回收空闲线程,若无可回收,则新建线程。
这四种创建线程的方式底层其实都是调用ThreadPoolExecutor的构造方法创建 ThreadPoolExecutor
ThreadPoolExecutor构造参数如下
-
int corePoolSize, 核心线程大小 线程池创建时,就初始化的线程数量
-
int maximumPoolSize,最大线程大小
-
long keepAliveTime, 超过corePoolSize的线程多久不活动被销毁时间 就是除核心线程外的线程,过了这段时间还是空闲就销毁
-
TimeUnit unit,时间单位 上面那参数的单位
-
BlockingQueue<Runnable> workQueue 任务队列 当任务数超过核心线程数时,多出的那些线程会放在任务队列中等待,若任务队列也满了,那么才创建非核心线程来执行
-
ThreadFactory threadFactory 线程池工厂 用来生产线程的,下面是默认的线程工场的代码,代码少我才贴的,大致就做了给创建的线程分组,命名,然后优先级都设置成了 5
-
RejectedExecutionHandler handler 拒绝策略 啥时候要拒绝呢,就是当队列+最大线程数都满足不了任务的执行时,多出来的任务没地放也没地执行的时候,这个时候我们需要舍弃了,是舍弃最开始运行的那几个线程呢,还是后面多出的线程呢,舍弃时抛异常还是不抛异常呢?主要就是如下前四种,默认是第一种Abort,舍弃后面来的多余的任务并抛异常,CallerRun是直接调用这些任务的run方法来执行,我也不抛弃你们,一起执行就完事了,DiscardOldest呢就是抛弃最早执行的那几个,也就是把前浪拍死在沙滩上,Discard呢也是舍弃后面多余的,但是不抛异常.
3.几种线程池的使用场景
newCachedThreadPool:
- 底层:返回ThreadPoolExecutor实例,corePoolSize为0;maximumPoolSize为Integer.MAX_VALUE;keepAliveTime为60L;时间单位TimeUnit.SECONDS;workQueue为SynchronousQueue(同步队列)
- 通俗:当有新任务到来,则插入到SynchronousQueue中,由于SynchronousQueue是同步队列,因此会在池中寻找可用线程来执行,若有可以线程则执行,若没有可用线程则创建一个线程来执行该任务;若池中线程空闲时间超过指定时间,则该线程会被销毁。
- 适用:执行很多短期的异步任务
newFixedThreadPool:
- 底层:返回ThreadPoolExecutor实例,接收参数为所设定线程数量n,corePoolSize和maximumPoolSize均为n;keepAliveTime为0L;时间单位TimeUnit.MILLISECONDS;WorkQueue为:new LinkedBlockingQueue<Runnable>() 无界阻塞队列
- 通俗:创建可容纳固定数量线程的池子,每个线程的存活时间是无限的,当池子满了就不再添加线程了;如果池中的所有线程均在繁忙状态,对于新任务会进入阻塞队列中(无界的阻塞队列)
- 适用:执行长期任务
newSingleThreadExecutor:
- 底层:FinalizableDelegatedExecutorService包装的ThreadPoolExecutor实例,corePoolSize为1;maximumPoolSize为1;keepAliveTime为0L;时间单位TimeUnit.MILLISECONDS;workQueue为:new LinkedBlockingQueue<Runnable>() 无解阻塞队列
- 通俗:创建只有一个线程的线程池,当该线程正繁忙时,对于新任务会进入阻塞队列中(无界的阻塞队列)
- 适用:按顺序执行任务的场景
NewScheduledThreadPool:
- 底层:创建ScheduledThreadPoolExecutor实例,该对象继承了ThreadPoolExecutor,corePoolSize为传递来的参数,maximumPoolSize为Integer.MAX_VALUE;keepAliveTime为0;时间单位TimeUnit.NANOSECONDS;workQueue为:new DelayedWorkQueue() 一个按超时时间升序排序的队列
- 通俗:创建一个固定大小的线程池,线程池内线程存活时间无限制,线程池可以支持定时及周期性任务执行,如果所有线程均处于繁忙状态,对于新任务会进入DelayedWorkQueue队列中,这是一种按照超时时间排序的队列结构
- 适用:执行周期性任务