java线程池讲解!核心参数

创建方式 | 构造方法
Executor构造方法

存放线程的容器:

 private final HashSet<Worker> workers = new HashSet<Worker>();

构造方法:

 public ThreadPoolExecutor(int corePoolSize,
                           int maximumPoolSize,
                           long keepAliveTime,
                           TimeUnit unit,
                           BlockingQueue<Runnable> workQueue,
                           ThreadFactory threadFactory,
                           RejectedExecutionHandler handler)

参数介绍:

救急线程(临时工)在阻塞队列满了才会创建,和核心线程最大的区别就是有个最大生存时间。----【会让核心线程一直运行】

  • 线程池的线程都是非守护线程?【不会随着主线程的结束而结束】

  • 救急线程的概念是在有界队列的前提下

  • corePoolSize:核心线程数,定义了最小可以同时运行的线程数量

  • maximumPoolSize:最大线程数,当队列中存放的任务达到队列容量时,当前可以同时运行的数量变为最大线程数,创建救急线程并立即执行最新的任务,与核心线程数之间的差值又叫救急线程数 -----【核心 + 救急 = 最大】

  • keepAliveTime:救急线程最大存活时间,当线程池中的线程数量大于 corePoolSize 的时候,如果这时没有新的任务提交,核心线程外的线程不会立即销毁,而是会等到 keepAliveTime 时间超过销毁

  • unit:keepAliveTime 参数的时间单位 ----【救急线程】

  • workQueue:阻塞队列,存放被提交但尚未被执行的任务

  • threadFactory:线程工厂,创建新线程时用到,可以为线程创建时起名字。【重写线程工厂内部方法不止是起名字的作用,还有线程组、守护线程、优先级等概念】负责创建线程

    • ThreadFactory接口有一个方法newThread(Runnable r),该方法用于创建新线程。

  • handler:拒绝策略,线程到达最大线程数仍有新任务时会执行拒绝策略。---【即核心线程和救急线程都处于繁忙才会进入拒绝策略,和自定义线程池不一样】

    RejectedExecutionHandler 下有 4 个实现类:

    • AbortPolicy:让调用者抛出 RejectedExecutionException 异常,默认策略

    • CallerRunsPolicy:让调用者运行的调节机制,将某些任务回退到调用者,从而降低新任务的流量

    • DiscardPolicy:直接丢弃任务,不予任何处理也不抛出异常

    • DiscardOldestPolicy:放弃队列中最早的任务,把当前任务加入队列中尝试再次提交当前任务

    补充:其他框架拒绝策略

    • Dubbo:在抛出 RejectedExecutionException 异常前记录日志,并 dump 线程栈信息,方便定位问题 ---【扩展AbortPolicy】

    • Netty:创建一个新线程来执行任务

    • ActiveMQ:带超时等待(60s)尝试放入队列

    • PinPoint:它使用了一个拒绝策略链,会逐一尝试策略链中每种拒绝策略 ---【责任链模式】

工作原理:

  1. 创建线程池,这时没有创建线程(懒惰),等待提交过来的任务请求,调用 execute 方法才会创建线程

  2. 当调用 execute() 方法添加一个请求任务时,线程池会做如下判断:

    • 如果正在运行的线程数量小于 corePoolSize,那么马上创建线程运行这个任务

    • 如果正在运行的线程数量大于或等于 corePoolSize,那么将这个任务放入队列

    • 如果这时队列满了且正在运行的线程数量还小于 maximumPoolSize,那么会创建救急线程立刻运行这个任务,对于阻塞队列中的任务不公平。这是因为创建每个 Worker(线程)对象会绑定一个初始任务,启动 Worker 时会优先执行

    • 如果队列满了且正在运行的线程数量大于或等于 maximumPoolSize,那么线程池会启动饱和拒绝策略来执行。【完全承载不了,迫不得已才会进入拒绝策略

  3. 当一个线程完成任务时,会从队列中取下一个任务来执行

  4. 当一个线程空闲超过一定的时间(keepAliveTime)时,线程池会判断:如果当前运行的线程数大于 corePoolSize,那么这个线程就被停掉,所以线程池的所有任务完成后最终会收缩到 corePoolSize 大小【只会停掉救急线程

总结

  • 线程池中刚开始没有线程,当一个任务提交给线程池后,线程池会创建一个新线程来执行任务。

  • 当线程数达到 corePoolSize 并没有线程空闲,这时再加入任务,新加的任务会被加入workQueue 队列排队,直到有空闲的线程。

  • 如果队列选择了有界队列,那么任务超过了队列大小时,会创建 maximumPoolSize - corePoolSize 数目的线程来救急。【tomcat线程池对这里进行了扩展?

  • 如果线程到达 maximumPoolSize 仍然有新任务这时会执行拒绝策略。拒绝策略 jdk 提供了 4 种实现,其它著名框架也提供了实现

  • 当高峰过去后,超过corePoolSize 的救急线程如果一段时间没有任务做,需要结束节省资源,这个时间由keepAliveTime 和 unit 来控制。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值