线程池的创建方式、七个参数、拒绝策略、阻塞队列、线程池大小设定

发布于:2024-03-28 ⋅ 阅读:(18) ⋅ 点赞:(0)

线程池的创建方式

1、通过Executors的静态方法可以创建四种类型的线程池。(不推荐)

1)FixedThreadPool 创建一个固定线程数的线程池,线程数量一直保持固定不变,如果任务提交时,没有空闲线程,那就进入任务队列,当有空闲时间时,再执行任务队列中的任务。

2)SingleThreadExecutor 线程池中始终只有一条线程。

3)CachedThreadPool 根据实际情况调整线程的数量,默认初始为0,当有任务提交时,创建线程去执行,当任务执行完毕,默认空闲等待60秒没有新任务提交就被销毁。

4)ScheduledThreadPool 可以在给定的延迟后或者定时运行任务。

PS:上面四种的任务队列长度最大都是Integer.MAX_VALUE,可能造成大量的请求堆积,从而OOM.

2、使用ThreadPoolExecutor()创建线程池。(推荐)

1)七个参数

corePoolSize 核心线程数,任务队列未到达最大容量时,最大可运行线程数。

maximumPoolSize 最大线程数,任务队列达到最大线程数时,最大可运行线程数。

keepALiveTime 存活时间,核心线程数之外的空闲线程存活时间

unit 时间单位,存活时间的时间单位

workQueue 任务队列,暂存等待执行的任务

threadFactory 线程工厂,用来创建线程,一般使用默认的

handler 拒绝策略,当达到最大线程数并且任务队列达到最大容量时,提交的任务会被拒绝,使用相应的拒绝策略。

PS:

线程池默认线程数量是0,当有任务提交时,会创建线程

当线程数达到核心线程数时,还有任务提交,会被暂存在先入先出的任务队列,保证有序性

当任务队列达到最大容量时,继续创建线程,线程达到最大线程数时,新提交的任务同样会进入任务队列

当任务队列再次达到最大容量时,使用拒绝策略

当线程执行完之后,空闲线程超过设置的存活时间,会被回收,直到线程数减少到核心线程数,回收才会停止

2) 拒绝策略

ThreadPoolExecutor.AbortPolicy: 抛出异常拒绝新任务。

ThreadPoolExecutor.CallerRunsPolicy:使用当前主线程执行新任务,慎选。

ThreadPoolExecutor.DiscardPolicy:直接丢弃新任务。

ThreadPoolExecutor.DiscardOldestPolicy:丢弃最早的新任务,也就是任务队列中最早未被处理的任务。

阻塞队列

LinkedBlockingQueue(基于链表的无界队列)

FixedThreadPool和ISingleThreadExecutor使用的是这种队列,队列最大可以达到Integer.MAX_VALUE,导致OOM。

SynchronousQueue(同步队列)

CacheThreadPool 使用的是这种队列,他不存放元素,当有新任务来时,有空闲线程就是用空闲线程,否则就创建线程,线程数最大也可以达到Integer.MAX_VALUE,导致创建大量的线程,导致OOM。

DelayedworkQueue(延迟阻塞队列)

ScheduleThreadPool使用这种线程,内部元素会按照定时时间先后排序,保证每次出队列的执行时间是最早的,内部会自动扩容,最大扩容到Integer.MAX_VALUE,导致OOM。

线程池的大小设定

对于CPU密集型任务,一般设定为N+1,多出来一条用来保证某个线程因为其他原因而暂停,让这一条去占用CPU执行任务,充分利用CPU空闲时间。

对于I/O密集型任务,一般设定为2N,与I/O 交互,需要等待I/O的响应,可以让出CPU,切换线程。

本文含有隐藏内容,请 开通VIP 后查看