在高并发场景下,如果每一个请求或人物都开启一个线程,系统要不断的进行线程的创建、销毁,会消耗大量的系统性能,而线程的数量到达一个临界值时,系统会受到进一步更大的影响,这时候就需要用到线程池。
ThreadPoolExecutor线程池的类关系
Executor的定义是An Object that executes submitted tasks,即接口的实现是一个“执行提交任务”的对象,接口提供了一个将“任务提交”和“执行机制”分离的方法,包括线程使用详情,调度等。总之是提供了一个提交Runnable任务的接口。
ExecutorService接口继承子Executor,提供了任务提交,执行,线程控制的一系列方法。
AbstractExecutorService是ExecutorService的默认实现,提供了任务提交,管理的默认实现。
ThreadPoolExecutor继承自AbstractExecutorService,是线程池的真正实现,通过构造方法的参数来配置生成不同的线程池,构造方法有:
public ThreadPoolExecutor(int corePoolSize, int maximumPoolSize, long keepAliveTime, TimeUnit unit, BlockingQueue<Runnable> workQueue); public ThreadPoolExecutor(int corePoolSize, int maximumPoolSize, long keepAliveTime, TimeUnit unit, BlockingQueue<Runnable> workQueue, ThreadFactory threadFactory) ; public ThreadPoolExecutor(int corePoolSize, int maximumPoolSize, long keepAliveTime, TimeUnit unit, BlockingQueue<Runnable> workQueue, RejectedExecutionHandler handler); public ThreadPoolExecutor(int corePoolSize, int maximumPoolSize, long keepAliveTime, TimeUnit unit, BlockingQueue<Runnable> workQueue, ThreadFactory threadFactory, RejectedExecutionHandler handler);
|
构造方法参数说明
1) corePoolSize,核心线程数,通常情况下会一直存活,不会受keepAliveTime的控制,即使是idle的空闲状态,除非设置
allowCoreThreadTimeOut为true。
2)maximumPoolSize,线程池最大线程数,线程池线程数达到这个数字,创建想成会被阻塞。任务队列为没有设置大小的LinkedBlockingDeque时,配置无效。
3)keepAliveTime,非核心且idle(空闲)状态的线程存活时间,超过这个时间就会被回收。
4)unit,keepAliveTime时间的单位
5)workQueue,线程池的任务队列,常用的任务队列有SynchronousQueue,LinkedBlockingDeque,ArrayBlockingQueue
6)threadFactory,线程创建工厂,用于创建新线程,定制个性化线程参数,一般使用DefaultThreadFactory 默认实现
7)RejectedExecutionHandler ,线程池的资源已全部被使用,添加线程失败后,执行rejectedExecution方法
线程池创建参数配置
当线程池任务队列无限大时
- 如果线程数量<=核心线程数量,那么直接启动一个核心线程来执行任务,不会放入队列中。
- 如果线程数量>核心线程数,但<=最大线程数,并且任务队列是LinkedBlockingDeque的时候,超过核心线程数量的任务会放在任务队列中排队。
- 如果线程数量>核心线程数,但<=最大线程数,并且任务队列是SynchronousQueue的时候,线程池会创建新线程执行任务,这些任务也不会被放在任务队列中。这些线程属于非核心线程,在任务完成后,闲置时间达到了超时时间就会被清除。
- 如果线程数量>核心线程数,并且>最大线程数,当任务队列是LinkedBlockingDeque,会将超过核心线程的任务放在任务队列中排队。也就是当任务队列是LinkedBlockingDeque并且没有大小限制时,线程池的最大线程数设置是无效的,他的线程数最多不会超过核心线程数。
- 如果线程数量>核心线程数,并且>最大线程数,当任务队列是SynchronousQueue的时候,会因为线程池拒绝添加任务而抛出异常。
当线程池任务队列有大小限制时
- 当LinkedBlockingDeque塞满时,新增的任务会直接创建新线程来执行,当创建的线程数量超过最大线程数量时会抛异常。
- SynchronousQueue没有数量限制。因为他根本不保持这些任务,而是直接交给线程池去执行。当任务数量超过最大线程数时会直接抛异常。
Executors线程池工厂、工具类提供了一些个性化的线程池配置,如:
newFixedThreadPool(int nThreads) ExecutorService newSingleThreadExecutor() ExecutorService newCachedThreadPool() ScheduledExecutorService newScheduledThreadPool(int corePoolSize, ThreadFactory threadFactory) |
- newFixedThreadPool,可重用、固定线程的线程池,基于共享的、无限的队列,在任何时候,线程都是活动状态,且可以处理任务,如果在所有线程都是活动状态时提交任务,任务将缓存在任务队列中等待,知道线程空闲下来,如果由于执行期间线程挂掉,将会创建新的线程执行任务。
- newSingleThreadExecutor,只有一个线程的线程池,基于无限队列,独苗线程挂掉后会重新创建,保证任务按照顺序执行,在任何给定时间,不会有多个任务处于活动状态
- newCachedThreadPool,根据需要创建新线程的线程池,但是线程可以重用,通常用于执行许多短期异步任务, 如果没有现有线程可用,则为新线程将创建线程并将其添加到池中。 线程未使用60秒将被终止并从中删除缓存。
- newScheduledThreadPool,延迟执行或定时执行任务的线程池。
(完)