加入收藏 | 设为首页 | 会员中心 | 我要投稿 马鞍山站长网 (https://www.0555zz.cn/)- 媒体处理、内容创作、云渲染、网络安全、业务安全!
当前位置: 首页 > 综合聚焦 > 编程要点 > 资讯 > 正文

你真的掌握线程池的七个参数是做什么的吗?

发布时间:2023-10-18 13:32:25 所属栏目:资讯 来源:
导读:可以介绍下关于队列的问题吗?
关于线程池的问题,大多数面试官会问线程池的几个参数的含义,今天就直接聊一聊线程池ThreadPoolExecutor。

先说下线程池中几个参数的含义:
ThreadPoolExecutor初始化的时候一般
可以介绍下关于队列的问题吗?
关于线程池的问题,大多数面试官会问线程池的几个参数的含义,今天就直接聊一聊线程池ThreadPoolExecutor。

先说下线程池中几个参数的含义:
ThreadPoolExecutor初始化的时候一般会有7个参数:

corePoolSize:核心线程数
maximumPoolSize:最大线程数
keepAliveTime:非核心线程保活时间
unit:单位
workQueue:队列
Executors.defaultThreadFactory():线程工厂
拒绝策略
ThreadPoolExecutor的工作原理:
往初始的线程池中提交线程池的第一个调用任务,底层会创建用于第一个调用的核心任务的线程,将线程和任务封装为一个woker对象放入set集合中,接下来每提交一个的任务都会对应创建一个核心线程和这个任务封装的woker对象放入set集合中,直到核心线程数达到corePoolSize,再次提交到线程池的任务会被放到阻塞队列排队执行,如果放队列的过程中,队列满了,就会创建一个非核心线程和这个任务封装为woker对象放入set集合中,如果最终已经达到最大线程数maximumPoolSize,就采用拒绝策略。如果放入队列过程中发现工作线程数为0,则创建一个空任务的Worker。

按位分割的好处就是用一个变量表示两个状态,在修改的时候可以利用cas保证原子性。

Worker对象创建逻辑是由addWorker方法实现的。

addWorker方法逻辑:
retry;双层循环
第一层循环主要判断:如果当前线程池状态为RUNNING就放行,如果状态为SHUTDOWN就必须满足传进来的新任务为null,队列中有待处理的任务才会放行(因为SHUTDOWN状态下不接受新任务,只处理队列中的任务);如果状态为STOP,IDYING,TERMINATED就一定不放行;

第二层循环主要是判断线程数,如果是创建核心线程,就判断是否达到corePoolSize,否则就判断是否达到maximumPoolSize,如果达到就返回fasle不放行。

如果未达到就放行,放行的时候会利用cas更新线程数,如果更新成功则两层循环结束,继续下面的逻辑。

因为是cas操作,多线程的情况下可能会有更新线程数量失败的情况,在这种情况下要判断之前获取的线程池状态和现在的线程池状态是否一致,如果不一致那就要重新判断状态,从而进入到外层循环的下一轮循环,如果一致就只需要进入到内层循环的下一轮循环。

创建Worker对象
接下来就是创建Worker(任务),Worker类继承aqs,封装了线程工厂,初始化的时候会利用工厂创建一个线程,并且和传进来的任务封装为worker对象。

获取线程池全局锁(reentrylock作为线程池全局锁),进行上锁操作

将创建的worker加入workers集合,workers是一个hashset集合。

放入集合后就可以解锁了

worker创建完成了,接下来就是启动线程,启动线程后就会执行worker中的run方法

run方法流程
这个方法中主要的逻辑是这段代码

复制
while (task != null || (task = getTask()) != null){
  逻辑
}
task是worker对象封装的任务。如果当前worker对象上没有任务就调用getTask去阻塞队列拿任务,如果能拿到就处理任务。如果getTask返回null就跳出循环,进入processWorkerExit方法。

我们知道线程池中的任务是放在队列中的,ThreadPoolExecutor中的队列一般默认是阻塞队列LinkedBlockingQueue,

getTask()方法会在这个队列中拿任务,如果有任务就直接返回任务,如果此时队列中无任务,当前线程会阻塞等待任务到来。

但是如果设置了非核心线程最大空闲时间keepAliveTime,代表非核心线程的worker对象中的线程在拿任务的时候不会用take方法,而是用poll,poll这个方法可以设置阻塞等待时间为keepAliveTime。当超过这个时间还没有任务就会返回null。所以我们需要在线程之间进行切换,如果我们不能切换到threadlocaltime,那么我们就需要使用getlasterror来实现。

(编辑:马鞍山站长网)

【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容!

    推荐文章