你了解线程池么?简单介绍一下
线程池是一种多线程处理形式,把任务的执行交由线程池来管理。如果每个请求都创建一个线程去处理,那么服务器的资源很快就会被耗尽,使用线程池可以减少创建和销毁线程的次数,每个工作线程都可以被重复利用,可执行多个任务。主要的优点就是线程复用和线程管理。
连接池 和 线程池是一个意思么?有什么区别?
- 相同点:都是事先准备好资源,避免频繁创建和销毁的代价。
- 不同点:连接池是面向数据库连接的;
线程池七大参数和四大拒绝策略
public ThreadPoolExecutor(int corePoolSize, // 核心线程数
int maximumPoolSize, // 最大线程数
long keepAliveTime, // 空闲线程存活时间
TimeUnit unit, // 时间单位
BlockingQueue<Runnable> workQueue, // 线程池任务队列
ThreadFactory threadFactory, // 创建线程的工厂
RejectedExecutionHandler handler // 拒绝策略
) {
//...
}
- 核心线程数 代表能够维护常用的线程开销,而 最大线程量 则代表最大能够创建的线程数。就是额定功率与最大功率的关系。
- 拒绝策略:当任务数超过最大线程数后,所执行的策略。
- AbortPolicy:拒绝并抛出异常。(默认使用的)
- CallerRunsPolicy:使用当前调用的线程来执行此任务。
- DiscardOldestPolicy:抛弃队列头部(最旧)的一个任务,并执行当前任务。
- DiscardPolicy:忽略并抛弃当前任务
线程池工作原理
核心线程数量过大或过小会造成什么后果?
- 当线程池中核心线程数量过大时,线程与线程之间会争取CPU资源,这样就会导致过多的上下文切换。上下文切换是指多个线程时间片轮转时的一次切换。
- 当线程池中的核心线程数量过少时,如果统一时间有大量任务需要处理,可能会导致大量任务在任务队列中排队等待执行,进而导致内存溢出(OOM)。
线程池都有哪些状态?
- RUNNING:线程池的初始化状态是RUNNING,能够接收新任务,以及对已添加的任务进行处理。
- SHUTDOWN:线程池处在SHUTDOWN状态时,不接收新任务,但能处理已添加的任务。 调用线程池的shutdown()接口时,线程池由RUNNING -> SHUTDOWN。
- STOP:线程池处在STOP状态时,不接收新任务,不处理已添加的任务,并且会中断正在处理的任务。 调用线程池的shutdownNow()接口时,线程池由(RUNNING or SHUTDOWN ) -> STOP。
- TIDYING:当所有的任务已终止,ctl记录的”任务数量”为0,线程池会变为TIDYING状态。当线程池变为TIDYING状态时,会执行钩子函数terminated()。terminated()在ThreadPoolExecutor类中是空的,若用户想在线程池变为TIDYING时,进行相应的处理;可以通过重载terminated()函数来实现。
- TERMINATED:线程池彻底终止,就变成TERMINATED状态。线程池处在TIDYING状态时,执行完terminated()之后,就会由 TIDYING -> TERMINATED。
都用过哪些线程池?(创建线程池有哪几种方式?)
- newCachedThreadPool:创建一个可缓存的线程池,若线程数超过处理所需,缓存一段时间后会回收,若线程数不够,则新建线程。
- newFixedThreadPool:创建一个固定大小的线程池,可控制并发的线程数,超出的线程会在队列中等待
- newSingleThreadExecutor:创建一个单线程的线程池,可保证所有任务按照指定顺序(FIFO, LIFO, 优先级)执行。
- newSingleThreadScheduledExecutor:建一个周期性的线程池,支持定时及周期性执行任务。
- newScheduledThreadPool:创建一个线程池,它可安排在给定延迟后运行命令或者定期的执行
- newWorkStealingPool:创建一个带并行级别的线程池,并行级别决定了同一时刻最多有多少个线程在执行,如不传并行级别参数,将默认为当前系统的CPU个数