线程池的执行原理,参数等知识点(面试常用)

线程池执行原理?

在这里插入图片描述

一个线程提交到线程池的处理流程如下:

  1. 如果此时线程池中的数量小于corePoolSize,即使线程池中的线程都处于空闲状态,也要创建新的线程来处理新任务
  2. 如果此时线程池中的数量等于corePoolSize,但是缓冲队列workQueue未满,将任务放入缓冲队列
  3. 如果此时线程池中的数量大于等于corePoolSize,缓冲队列workQueue满,并且线程池中的数量小于maximumPoolSize创建新的线程来处理新任务
  4. 如果线程池中的数量等于maximumPoolSize,使用 handler拒绝策略进行处理

线程池的一些参数

corePoolSize:线程池的基本大小。线程池中会维护一个最小的线程数量corePoolSize,如果线程池中的线程数量小于corePoolSize,即使有些线程处理空闲状态,它们也不会被销毁。
poolSize:线程池中当前线程的数量。
BlockingQueue:存储等待运行的任务。
keepAliveTime:空闲线程存活时间。一个线程如果处于空闲状态,并且当前的线程数量大于corePoolSize,那么在指定时间后,这个空闲线程会被销毁
maximumPoolSize:线程池中允许的最大线程数。
workQueue 工作队列。新任务被提交后,会先进入到此工作队列中,任务调度时再从队列中取出任务。
handler 拒绝策略。线程池中的线程数量也达到最大值(maximumPoolSize),这时如果有新任务提交进来,就是触发handler。

workQueue四种队列

  1. ArrayBlockingQueue

基于数组的有界阻塞队列,按FIFO排序。

  1. LinkedBlockingQueue

基于链表的无界阻塞队列(但其实它的最大容量为Interger.MAX),按照FIFO排序。由于该队列的近似无界性,基本不会满(很难达到Interger.MAX这个数),因此使用该工作队列时,参数maxPoolSize其实是不起作用的。

  1. SynchronousQueue

因为SynchronousQueue没有容量,实际上它不是一个真正的队列。它只是维护一组线程,这些线程在等待着把元素加入或移出队列。 发送或者消费线程的行为都会被阻塞,只有当一对消费和发送线程匹配上时,才同时退出。

  1. PriorityBlockingQueue

具有优先级的无界阻塞队列,优先级通过参数Comparator实现。

handler四种拒绝策略

  1. AbortPolicy(默认策略)
    特点:当任务无法被提交时,直接抛出RejectedExecutionException异常。
    适用场景:任务提交失败后,需要立即得知该情况并进行处理。

  2. CallerRunsPolicy
    特点:当任务无法被提交时,直接丢弃该任务,不抛出任何异常
    适用场景:任务的重要性相对较低,或者系统资源紧张时,优先保证系统的稳定运行。

  3. DiscardPolicy
    特点:当任务无法被提交时,会丢弃队列中等待最久的任务,然后尝试再次提交当前任务。
    适用场景:任务之间有优先级差异,或者新任务比旧任务更有价值的情况。

  4. CallerRunsPolicy
    特点:当任务无法被提交时,不丢弃任务,也不抛出异常,而是由调用线程(即提交任务的线程)直接执行该任务
    适用场景:希望系统在高负载时能够自我调节,而不是简单地拒绝任务。

如何设置拒绝策略

在创建ThreadPoolExecutor时,可以通过构造函数的参数来设置拒绝策略
示例:

RejectedExecutionHandler rejectedHandler = new ThreadPoolExecutor.CallerRunsPolicy();  
ThreadPoolExecutor executor = new ThreadPoolExecutor(  
    corePoolSize,   
    maximumPoolSize,   
    keepAliveTime,   
    TimeUnit.SECONDS,   
    workQueue,   
    rejectedHandler  
);

为什么要设置线程池大小

如果线程池线程数量太小,当有大量请求需要处理,系统响应比较慢,会出现任务队列大量堆积任务导致OOM。
如果线程池线程数量过大,大量线程可能会同时抢占 CPU 资源,这样会导致大量的上下文切换,从而增加线程的执行时间,影响了执行效率。

线程池大小怎么设置?

CPU密集型任务(N+1): 系统的硬盘、内存性能相对CPU要好很多时使用该设置思路。要进行大量的计算,消耗CPU资源,可以将线程数设置为N(CPU 核心数)+1

I/O密集型任务(2N): CPU性能相对硬盘、内存要好很多时使用该设置思路。CPU经常处于空闲状态,因为它在等待外部I/O操作完成。通常我们会开CPU核心数数倍的线程

线程池的类型有哪些?适用场景?

CachedThreadPool——可缓存线程池。线程的创建数量几乎没有限制
newFixedThreadPool————指定线程数量
newSingleThreadExecutor————单线程的Executor
只创建唯一的线程来执行任务。保证任务按照指定顺序(FIFO,LIFO,优先级)执行
newScheduleThreadPool——定时线程池支持定时及周期性任务执行。

  • 9
    点赞
  • 5
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值