• 多线程之ThreadPoolExecutor


    关系类图为:

    在这里插入图片描述

    1 线程池状态

    ThreadPoolExecutor 使用 int 的高 3 位来表示线程池状态,低 29 位表示线程数量

    状态名高3位接收新任务处理阻塞队列任务说明
    RUNNING111YY
    SHUTDOWN000NY不会接收新任务,但会处理阻塞队列剩余 任务
    STOP001NN会中断正在执行的任务,并抛弃阻塞队列 任务
    TIDYING010任务全执行完毕,活动线程为 0 即将进入 终结
    TERMINATED011终结状态

    从数字上比较,TERMINATED > TIDYING > STOP > SHUTDOWN > RUNNING

    信息存储在一个原子变量 ctl 中,目的是将线程池状态与线程个数合二为一,这样就可以用一次 cas 原子操作 进行赋值

    // c 为旧值, ctlOf 返回结果为新值
    ctl.compareAndSet(c, ctlOf(targetState, workerCountOf(c))));
    // rs 为高 3 位代表线程池状态, wc 为低 29 位代表线程个数,ctl 是合并它们
    private static int ctlOf(int rs, int wc) { return rs | wc; }
    
    • 1
    • 2
    • 3
    • 4

    2 构造方法

    public ThreadPoolExecutor(int corePoolSize,
     int maximumPoolSize,
     long keepAliveTime,
     TimeUnit unit,
     BlockingQueue<Runnable> workQueue,
     ThreadFactory threadFactory,
    RejectedExecutionHandler handler)
    /*
    参数说明:
    corePoolSize 核心线程数目 
    maximumPoolSize 最大线程数目
    keepAliveTime 生存时间 
    unit 时间单位 
    workQueue 阻塞队列
    threadFactory 线程工厂 - 可以为线程创建时起个好名字
    handler 拒绝策略
    */
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17

    工作方式:

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

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

    • 如果队列选择了有界队列,那么任务超过了队列大小时,会创建 maximumPoolSize - corePoolSize 数目的线 程来救急

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

      • jdk
        • AbortPolicy 让调用者抛出 RejectedExecutionException 异常,默认策略
        • CallerRunsPolicy 让调用者运行任务
        • DiscardPolicy 放弃本次任务
        • DiscardOldestPolicy 放弃队列中最早的任务,本任务取而代之
      • Dubbo 的实现,在抛出 RejectedExecutionException 异常之前会记录日志,并 dump 线程栈信息,方 便定位问题
      • Netty 的实现,是创建一个新线程来执行任务
      • ActiveMQ 的实现,带超时等待(60s)尝试放入队列
      • PinPoint 的实现,它使用了一个拒绝策略链,会逐一尝试策略链中每种拒绝策略 (类似责任链那种)
    • 当高峰过去后,超过corePoolSize 的救急线程如果一段时间没有任务做,需要结束节省资源,这个时间由 keepAliveTime 和 unit 来控制。

    拒绝策略类图

    在这里插入图片描述

  • 相关阅读:
    WPF 用户控件依赖注入赋值
    漫谈计算机网络:物理层 ----- 双绞线&光纤?,从最底层开始了解计算机网络
    超详细反编译python打包的exe
    数据驾驶舱只是面子工程?它的真正作用你根本就不了解
    STM8S芯片问题,批量生产时,板子烧录完程序,放置半个月,1%的板子就开不开机了或者1秒开关机一次,300次内板子必死机
    Cypress学习记录之一:简介和安装
    【5 树与二叉树】判断两个二叉树是否相同。
    使用VsCode搭建Vue开发环境
    SAP MM ME27 创建公司内STO单
    java计算机毕业设计疆域特色农家乐系统MyBatis+系统+LW文档+源码+调试部署
  • 原文地址:https://blog.csdn.net/ABestRookie/article/details/126274823