【线程池的使用规范、线程池的7个参数、4种拒绝策略、线程池的5种状态、线程池的执行流程】

在这里插入图片描述

一.线程池的使用规范

阿里巴巴开发手册规定,线程池不允许使用 Executors 去创建,而是通过 ThreadPoolExecutor 的方式,这样的处理方式让开发人员更加明确线程池的运行规则,规避资源耗尽的风险。
说明:Executors 返回的线程池对象的弊端如下:

  1. FixedThreadPool 和 SingleThreadPool:
    允许的请求队列长度为 Integer.MAX_VALUE,可能会堆积大量的请求,从而导致 OOM。
  2. CachedThreadPool:
    允许的创建线程数量为 Integer.MAX_VALUE,可能会创建大量的线程,从而导致 OOM。

二.线程池的7个参数你都知道吗?

构造方法中的参数信息
在这里插入图片描述
查看源代码

/**
     * Creates a new {@code ThreadPoolExecutor} with the given initial
     * parameters.
     *
     * @param corePoolSize the number of threads to keep in the pool, even
     *        if they are idle, unless {@code allowCoreThreadTimeOut} is set
     * @param maximumPoolSize the maximum number of threads to allow in the
     *        pool
     * @param keepAliveTime when the number of threads is greater than
     *        the core, this is the maximum time that excess idle threads
     *        will wait for new tasks before terminating.
     * @param unit the time unit for the {@code keepAliveTime} argument
     * @param workQueue the queue to use for holding tasks before they are
     *        executed.  This queue will hold only the {@code Runnable}
     *        tasks submitted by the {@code execute} method.
     * @param threadFactory the factory to use when the executor
     *        creates a new thread
     * @param handler the handler to use when execution is blocked
     *        because the thread bounds and queue capacities are reached
     * @throws IllegalArgumentException if one of the following holds:<br>
     *         {@code corePoolSize < 0}<br>
     *         {@code keepAliveTime < 0}<br>
     *         {@code maximumPoolSize <= 0}<br>
     *         {@code maximumPoolSize < corePoolSize}
     * @throws NullPointerException if {@code workQueue}
     *         or {@code threadFactory} or {@code handler} is null
     */
    public ThreadPoolExecutor(int corePoolSize,
                              int maximumPoolSize,
                              long keepAliveTime,
                              TimeUnit unit,
                              BlockingQueue<Runnable> workQueue,
                              ThreadFactory threadFactory,
                              RejectedExecutionHandler handler) {
        if (corePoolSize < 0 ||
            maximumPoolSize <= 0 ||
            maximumPoolSize < corePoolSize ||
            keepAliveTime < 0)
            throw new IllegalArgumentException();
        if (workQueue == null || threadFactory == null || handler == null)
            throw new NullPointerException();
        this.acc = System.getSecurityManager() == null ?
                null :
                AccessController.getContext();
        this.corePoolSize = corePoolSize;
        this.maximumPoolSize = maximumPoolSize;
        this.workQueue = workQueue;
        this.keepAliveTime = unit.toNanos(keepAliveTime);
        this.threadFactory = threadFactory;
        this.handler = handler;
    }
  1. corePoolSize 线程池核心线程大小

线程池中会维护一个最小的线程数量,即使这些线程处理空闲状态,他们也不会被销毁,除非设置了allowCoreThreadTimeOut。这里的最小线程数量即是corePoolSize。任务提交到线程池后,首先会检查当前线程数是否达到了corePoolSize,如果没有达到的话,则会创建一个新线程来处理这个任务。

  1. maximumPoolSize 线程池最大线程数量

当前线程数达到corePoolSize后,如果继续有任务被提交到线程池,会将任务缓存到工作队列(后面会介绍)中。如果队列也已满,则会去创建一个新线程来出来这个处理。线程池不会无限制的去创建新线程,它会有一个最大线程数量的限制,这个数量即由maximunPoolSize指定。

  1. keepAliveTime 空闲线程存活时间

一个线程如果处于空闲状态,并且当前的线程数量大于corePoolSize,那么在指定时间后,这个空闲线程会被销毁,这里的指定时间由keepAliveTime来设定

  1. unit 空闲线程存活时间单位

keepAliveTime 空闲线程存活时间计量单位
在这里插入图片描述

  1. workQueue 工作队列
    新任务被提交后,会先进入到此工作队列中,任务调度时再从队列中取出任务。jdk中提供了四种工作队列:
    在这里插入图片描述
    ①ArrayBlockingQueue
    1.基于数组的有界阻塞队列,按FIFO排序。
    2.新任务进来后,会放到该队列的队尾,有界的数组可以防止资源耗尽问题。
    3.当线程池中线程数量达到corePoolSize后,再有新任务进来,则会将任务放入该队列的队尾,等待被调度。
    4.如果队列已经是满的,则创建一个新线程,如果线程数量已经达到maxPoolSize,则会执行拒绝策略。
    在这里插入图片描述

②LinkedBlockingQuene
1.基于链表的无界阻塞队列(最大容量为Interger.MAX),按照FIFO排序。
2.由于该队列的近似无界性,当线程池中线程数量达到corePoolSize后,再有新任务进来,会一直存入该队列,而基本不会去创建新线程直到maxPoolSize(很难达到Interger.MAX这个数)。
3.使用该工作队列时,参数maxPoolSize其实是不起作用的。
在这里插入图片描述

③SynchronousQuene
1.一个不缓存任务的阻塞队列,生产者放入一个任务必须等到消费者取出这个任务。
2.新任务进来时,不会缓存,直接被调度执行该任务,如果没有可用线程,则创建新线程,如果线程数量达到maxPoolSize,则执行拒绝策略。
在这里插入图片描述

④PriorityBlockingQueue
1.具有优先级的无界阻塞队列。
2.优先级通过参数Comparator实现。
在这里插入图片描述

  1. threadFactory 线程工厂
    创建一个新线程时使用的工厂,可以用来设定线程名、是否为daemon线程等操作。
    在这里插入图片描述

  2. handler 拒绝策略
    当工作队列中的任务已到达最大限制,并且线程池中的线程数量也达到最大限制,这时如果有新任务提交进来,我们通过拒绝策略来解决这个问题,jdk中提供了4中拒绝策略:
    在这里插入图片描述
    ①CallerRunsPolicy
    该策略下,在调用者线程中直接执行被拒绝任务的run方法,除非线程池已经shutdown,则直接抛弃任务。
    在这里插入图片描述

②AbortPolicy
该策略下,直接丢弃任务,并抛出RejectedExecutionException异常。
在这里插入图片描述

③DiscardPolicy
该策略下,直接丢弃任务,什么都不做。
在这里插入图片描述

④DiscardOldestPolicy
该策略下,抛弃进入队列最早的那个任务,然后尝试把这次拒绝的任务放入队列
在这里插入图片描述

三.线程池的5种状态

在这里插入图片描述

  1. RUNNING

    • 线程池被创建,线程池的状态就是RUNNING状态;
    • 线程池处于RUNNING状态时,线程池能够接收新任务,也能够对已经添加的任务进行处理;
  2. SHUTDOWN

    • 线程池已经被关闭了,不再接收新任务;但是,其还是会处理队列中的剩余的任务;
    • 调用线程池的shutdown()方法后,线程池的状态就会由RUNNING转为SHUTDOWN;
  3. STOP

    • 线程池处于STOP状态,此时线程池不再接收新任务,不处理已经添加进来的任务,并且会中断正在处理的任务;
    • 调用线程池的shutdownNow()方法后,线程池的状态就会由RUNNING或SHUTDOWN转为STOP;
  4. TIDYING

    • 线程池被下达关闭命令后,如果当前所有的任务都已经终止了(这个终止可以表示执行结束,也可以表示强制中断,也可以表示被丢弃) ,那么线程就会进入TIDYING状态;当线程池变为TIDYING状态时,会执行钩子函数terminated()。terminated()在ThreadPoolExecutor类中是空的,若用户想在线程池变为TIDYING时,进行相应的处理;可以通过重载terminated()函数来实现。
    • 如果线程状态已经是SHUTDOWN了,并且线程中以及队列中都没有任务时,线程池就会由SHUTDOWN转为TIDYING;如果线程池状态为STOP,那么当线程池把所有的任务都给清理干净时,线程池就会由STOP转为TIDYING;
  5. TERMINATED;

    • 线程池结束,不能重新启动了;
    • 如果线程池处于TIDYING状态,那么当线程池执行完terminated()方法后,线程池状态就会由TIDYING转为TERMINTED;

四.线程池的执行流程

  1. 提交任务后会首先进行当前工作线程数与核心线程数的比较,如果当前工作线程数小于核心线程数,则直接调用 addWorker() 方法创建一个核心线程去执行任务;

  2. 如果工作线程数大于核心线程数,即线程池核心线程数已满,则新任务会被添加到阻塞队列中等待执行,当然,添加队列之前也会进行队列是否为空的判断;

  3. 如果线程池里面存活的线程数已经等于核心线程数了,且阻塞队列已经满了,再会去判断当前线程数是否已经达到最大线程数 maximumPoolSize,如果没有达到,则会调用 addWorker() 方法创建一个非核心线程去执行任务;

  4. 如果当前线程的数量已经达到了最大线程数时,当有新的任务提交过来时,会执行拒绝策略

在这里插入图片描述

五.总结

学习不仅输入,还要输出,接下来我们一起来回顾一下这篇文章的内容吧

  1. 线程池的使用规范
  2. 线程池的7的参数
  3. 线程池的4种拒绝策略
  4. 线程池的5种状态
  5. 线程池的执行流程

好了,具体的细节没有想起来的可以翻上去看看,这篇文章就学习到这里,接下来我们一起来学习关于多线程相关的知识。

你准备好了吗?来吧在这里插入图片描述

我是硕风和炜,我们下篇文章见哦。

  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

硕风和炜

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值