你了解Java线程池的原理吗?

54 阅读3分钟

你了解Java线程池的原理吗?

重要内容

Java 线程池(Executor)是 Java 提供的一种用于管理和重用线程的机制,通过它可以避免频繁创建和销毁线程的开销,提高程序的性能

线程池的工作流程

当我们向线程池提交任务时,线程池会按照以下步骤处理

  1. 检查核心线程数量:如果线程池中的线程数小于核心线程数,线程池会立即创建新的线程来执行任务
  2. 检查任务队列:如果线程池中的线程数已达到核心线程数,新的任务会被添加到任务队列中,等待有线程空闲时执行
  3. 检查最大线程数:如果任务队列已满,线程池会检查线程数是否小于最大线程数。如果小于,线程池会创建新的线程来执行任务
  4. 拒绝策略:如果线程池中的线程数达到了最大线程数,且任务队列已满,线程池会根据设定的拒绝策略来处理新任务

扩展内容

线程池的组成

Java 线程池主要由以下几部分组成

public ThreadPoolExecutor( int corePoolSize,                  // 核心线程数
                           int maximumPoolSize,               // 最大线程数
                           long keepAliveTime,                // 空闲存活时间
                           TimeUnit unit,                     // 时间单位
                           BlockingQueue<Runnable> workQueue, // 工作队列
                           ThreadFactory threadFactory,       //线程工厂
                           RejectedExecutionHandler handler)  // 拒绝策略
  • 线程池核心线程:线程池启动时会创建的线程数量,这些线程会一直保持存活,除非线程池关闭或发生一些特殊情况(比如 allowCoreThreadTimeOut 设置为true时,核心线程也可以在空闲一定时间后被回收)
  • 最大线程数:线程池中线程的最大数量。即使所有核心线程都在工作,线程池也可以通过创建新的线程来处理更多的任务,直到达到最大线程数
  • 工作队列:线程池使用的队列,用于存放待执行的任务
    • LinkedBlockingQueue :基于链表的阻塞队列,支持无限任务排队
    • ArrayBlockingQueue :固定长度的阻塞队列,任务队列长度有限
    • SynchronousQueue :特殊的队列,它不存储任何任务,每当有新任务到来时,必须有空闲线程才能执行
    • PriorityBlockingQueue :带优先级的无界阻塞队列
  • 拒绝策略:当线程池中的线程数达到最大线程数,且任务队列已满时,线程池会根据设定的拒绝策略来处理新的任务
    • AbortPolicy :抛出 RejectedExecutionException 异常
    • CallerRunsPolicy :由调用线程执行任务,避免线程池崩溃
    • DiscardPolicy :丢弃任务,不抛出异常
    • DiscardOldestPolicy :丢弃任务队列中最旧的任务

图解线程池的工作流程

如果线程池中的线程数小于核心线程数,线程池会立即创建新的线程来执行任务

image-20250514132026250

如果线程池中的线程数已达到核心线程数,新的任务会被添加到任务队列中,等待有线程空闲时执行

image-20250514132056995

如果任务队列已满,线程池会检查线程数是否小于最大线程数。如果小于,线程池会创建新的线程来执行任务

image-20250514132228145

如果线程池中的线程数达到了最大线程数,且任务队列已满,线程池会根据设定的拒绝策略来处理新任务

image-20250514132254789