【多线程】ThreadPoolExecutor运行逻辑详解

发布于:2023-01-04 ⋅ 阅读:(235) ⋅ 点赞:(0)

概念

  • 线程过多会带来额外的开销,其中包括创建销毁线程的开销、调度线程的开销等等;
  • 为了解决以上问题,JDK提出了线程池,用来维护多个线程,这种做法,一方面避免了处理任务时创建销毁线程开销的代价,另一方面避免了线程数量膨胀导致的过分调度问题,保证了对内核的充分利用;

线程池优点

  • 降低资源消耗,通过重复利用已创建的线程降低线程创建和销毁造成的消耗;
  • 提高响应速度,当任务到达时,任务可以不需要等到线程创建就能立即执行;
  • 提高线程的可管理性,线程是稀缺资源,如果无限制的创建,不仅会消耗系统资源,还会降低系统的稳定性,使用线程池可以进行统一的分配,调优和监控;

ThreadPoolExecutor参数解释

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

其中的构造参数的作用如下:

  • corePoolSize:
    • 核心线程数。提交任务时,当线程池中的线程数 小于 corePoolSize 时,会 新 创建一个核心线程执行任务。当线程数 等于 corePoolSize 时,会将任务 添加进任务队列;
  • maximumPoolSize:
    • 最大线程数。提交任务时,当 任务队列已满 并且线程池中的总线程数 不大于 maximumPoolSize 时,线程池会令非核心线程执行提交的任务。当 大于 maximumPoolSize 时,会执行拒绝策略;
  • keepAliveTime:
    • 非核心线程 空闲时 的存活时间;
  • unit:
    • keepAliveTime 的单位;
  • workQueue:
    • 任务队列(阻塞队列);
  • threadFactory:
    • 线程工厂,线程池用来新创建线程的工厂类;
  • handler:
    • 拒绝策略,线程池遇到无法处理的情况时会执行该拒绝策略选择抛弃或忽略任务等;

ThreadPoolExecutor运行流程

在这里插入图片描述

  • 当有新的任务投递时,首先会判断当前线程数是否小于核心线程数,如果小于,则创建线程并执行;
  • 如果大于核心线程数,那么会继续判断当前队列是否已满,如果未满,则添加任务到阻塞队列,等待执行;
  • 如果当前队列已满,那么会判断当前线程是否小于最大线程,如果小于,则添加线程继续执行;
  • 如果当前运行线程大于最大线程,则会走拒绝策略;

ThreadPoolExecutor拒绝策略

  • ThreadPoolExecutor提供了四个拒绝策略,分别为CallerRunsPolicy,AbortPolicy,DiscardPolicy以及DiscardOldestPolicy

CallerRunsPolicy

  • 会调用当前线程池的所在的线程去执行被拒绝的任务;

AbortPolicy

  • 默认的拒绝策略,响应为直接抛出异常;(RejectedExecutionException

DiscardPolicy

  • 啥也没干,不会抛出异常,也不会执行;

DiscardOldestPolicy

  • 会抛弃队列中最旧的任务,然后把此任务添加进去;
本文含有隐藏内容,请 开通VIP 后查看