• 线程池的简单理解


    ​📒个人主页:热爱生活的李📒
    ​❤️感谢大家阅读本文,同时欢迎访问本人主页查看更多文章​❤️
    🙏本人也在学习阶段,如若发现问题,请告知,非常感谢🙏

    ThreadPoolExecutor

    线程池状态

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

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

    构造方法

    参数名参数含义
    corePoolSize核心线程数目
    maximumPoolSize最大线程数目
    keepAliveTime生存时间-针对救急线程
    unit时间单位-针对救急线程
    workQueue阻塞队列
    threadFactory线程工厂
    handler拒绝队列

    1、当线程池中刚开始是没有线程的,当一个任务提交给线程池后,线程池才会创建一个新线程来执行任务
    2、当线程池达到corePoolSize并没有线程空闲时候,这时再加入任务,新加的任务会被加入到workQueue队列排队,直到有空闲线程
    3、如果有界队列满了且没有空闲线程,就会创建maximumPoolSize-corePoolSize数目的救急线程
    4、如果线程达到了maximumPoolSize仍然有新任务这时就会执行拒绝策略
    抛出RejectedExecutionException异常,这是默认策略
    CallerRunPolicy让调用者运行任务
    DiscardPolicy放弃本次任务
    DiscardOldestPolicy放弃队列中最早的任务
    5、当高峰过去后,救急线程如果一段时间没有任务做,需要结束节省资源

    newFixedThreadPool

    特点
    核心线程数==最大线程数,没有救急线程
    阻塞队列是无界的,可以放任意数量的任务
    使用于任务量已知,相对耗时的任务

    newCachedThreadPool

    特点
    核心线程数是0,最大线程数是Integer。MAX_VALUE,救急线程的生存空间的60s
    队列采用SynchronousQueue实现特点是,它没有容量,没有线程来取是放不进去的
    整个线程池表现为线程池数会根据任务量不断增长,没有增长,当任务执行完毕,空闲1分钟后释放线程
    适合任务数比较密集,但每个任务执行时间较短的情况

    newSingleThreadExecutor
    使用场景
    希望多个任务排队执行。线程数固定为1,任务数多于1时会放入无界队列排队,任务执行完毕,这唯一的线程也不会被释放
    区别
    自己创建一个单线程串行执行任务,如果任务执行失败而终止那么没有补救条件,而线程池还会再创建一个线程,保证池的正常操作

    newScheduledThreadPool

    执行方法

    void execute(Runnable command);
    执行任务

    Future submit(Callable task)
    提交任务task,用返回值Future获取任务执行结果

    List invokeAll(Collection tasks)
    提交tasks中所有的任务

    List invokeAll(Collection tasks, long timeout, TimeUnit unit)
    提交tasks中所有的任务带超时时间

    T invokeAny(Collection tasks)
    提交tasks中的任务那个先执行完毕返回该任务的结果其它任务取消

    T invokeAny(Collection tasks,long timeout, TimeUnit unit)
    提交tasks中的任务那个先执行完毕返回该任务的结果其它任务取消带超时时间

    关闭线程池

    shutdown()
    线程池状态修改为SHUTDOWN
    不会接收新的任务
    但已提交的会执行完
    只打断空闲线程
    此方法不会阻塞调用线程的执行

        public void shutdown() {
            final ReentrantLock mainLock = this.mainLock;
            mainLock.lock();
            try {
                checkShutdownAccess();
                //修改线程池状态
                advanceRunState(SHUTDOWN);
                //打断空闲线程
                interruptIdleWorkers();
                onShutdown(); // hook for ScheduledThreadPoolExecutor
            } finally {
                mainLock.unlock();
            }
            //尝试终结
            tryTerminate();
        }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16

    shutdownNow
    修改线程池状态为stop
    不接收新任务
    打断所有线程
    会将队列中的任务返回

        public List<Runnable> shutdownNow() {
            List<Runnable> tasks;
            final ReentrantLock mainLock = this.mainLock;
            mainLock.lock();
            try {
                checkShutdownAccess();
                //修改线程池状态
                advanceRunState(STOP);
                //打断所有线程
                interruptWorkers();
                //获取队列这种剩余任务
                tasks = drainQueue();
            } finally {
                mainLock.unlock();
            }
            tryTerminate();
            return tasks;
        }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
  • 相关阅读:
    人类小脑内在组织背后的基因图谱
    习题7-4 求矩阵各行元素之和
    iOS开发基础102-后台保活方案
    git 相关命令
    【Cadence】配置文件cdsinit和cdsenv的使用
    探秘SuperCLUE-Safety:为中文大模型打造的多轮对抗安全新框架
    关于多个elementui的cascader级联组件页面滚动渲染样式导致卡顿问题
    2、模块传参和依赖
    数据库语句
    决策树原理以及在sklearn中的使用
  • 原文地址:https://blog.csdn.net/weixin_51538712/article/details/127119317