线程池简析

线程的本质

线程池简析


Java 线程池

  • newCachedThreadPool
    • 创建一个可缓存的无界线程池,该方法无参数。
    • 只有非核心线程,线程数量不定的线程池,为无限大,最大线程数为Integer.MAX_VALUE
    • keepAliveTime为60秒
    • 使用SynchronousQueue作为工作队列。这种队列不存储元素,任务提交后必须有空闲线程立即接收,否则会创建新线程(如果未达到maximumPoolSize)。
    • 如果任务提交速度过快,会创建大量线程(理论上可达Integer.MAX_VALUE个),可能耗尽系统资源,导致OOM以及频繁的上下文切换。
  • newFixedThreadPool
    • 创建一个定长线程池
    • 使用无界的LinkedBlockingQueue作为工作队列
    • 无超时机制
    • 当任务提交速度远大于处理速度时,队列会持续增长,可能导致内存溢出(OOM)
  • newSingleThreadExecutor
    • 创建只有一个线程的线程池,该方法无参数
    • 所有任务都保存无界的LinkedBlockingQueue中,等待唯一的单线程来执行任务,并保证所有任务按照指定顺序(FIFO或优先级)执行。
    • 无界队列可能导致OOM
  • newScheduledThreadPool/newSingleThreadScheduledExecutor
    • 创建一个定长线程池,支持定时及周期性任务执行。ScheduledExecutorService比Timer更安全,功能更强大
    • 可指定线程池的核心线程个数
    • 非核心数量无限制,maximumPoolSize为Integer.MAX_VALUE。但由于队列是DelayedWorkQueue,通常不会无限增长线程,除非有大量同时到期的任务且处理不过来
    • 非核心线程闲置时立即被回收
    • 任务队列是DelayedWorkQueue (一种特殊的PriorityQueue)

线程池参数

corePoolSize:

  • 如果当前运行的线程数小于corePoolSize,则创建新线程(即使有空闲的核心线程)来执行任务。
  • 除了利用提交新任务来创建和启动线程(按需构造),也可以通过 prestartCoreThread() 或 prestartAllCoreThreads() 方法来提前启动线程池中的基本线程。

maximumPoolSize:

  • 如果workQueue.offer()失败(队列已满),创建小于maximumPoolSize的线程
  • 如果是有界队列,当队列满时,仍然有任务进来,此时线程池会创建小于最大线程数的线程。
  • 如果是无界队列,会一直保持核心线程数,多余的任务会一直往队列中加入。

keepAliveTime:

  • 非核心线程空闲存活时间
  • allowCoreThreadTimeOut(boolean) 方法也可将此超时策略应用于核心线程
  • 也可以使用setKeepAliveTime()动态地更改参数

workQueue:

  • 阻塞队列,核心线程数满时,新加入的任务,会先添加到阻塞队列中等待线程获取任务并执行。
  • BlockingQueue的插入/移除/检查这些方法,对于不能立即满足但可能在将来某一时刻可以满足的操作,共有4种不同的处理方式
    • 第一种是抛出一个异常
    • 第二种是返回一个特殊值(null 或 false,具体取决于操作)
    • 第三种是在操作可以成功前,无限期地阻塞当前线程
    • 第四种是在放弃前只在给定的最大时间限制内阻塞。

threadFactory:

  • 创建新线程的工厂
  • 可以为线程池中的线程设置更有意义的名称、设置守护线程状态、设置线程优先级、指定UncaughtExceptionHandler等
  • Executors.defaultThreadFactory()是默认实现

handler:

  • 核心线程和非核心线程都已用尽,且队列也满了,执行RejectedExecutionHandler所定义的拒绝策略
  • 线程饱和策略,默认策略为AbortPolicy,直接在当前线程抛出异常。
  • 实现RejectedExecutionHandler接口自定义拒绝策略,可以做一些打印观察日志的操作,告警、兜底的相关处理等。
  • ThreadPoolExecutor.AbortPolicy:处理程序遭到拒绝,则直接抛出运行时异常 RejectedExecutionException。(默认策略)
  • ThreadPoolExecutor.CallerRunsPolicy:提交任务的线程,直接执行任务。此策略提供简单的反馈控制机制,变相的背压机制,能够减缓新任务的提交速度。
  • ThreadPoolExecutor.DiscardPolicy:直接丢弃被拒绝的任务,不做任何通知
  • ThreadPoolExecutor.DiscardOldestPolicy:位于工作队列头部的任务(最旧的任务)将被删除,然后重新尝试执行任务(如果再次失败,则重复此过程)。

线程池类

  • Executor
    • 顶层接口
    • 将任务提交和任务执行进行解耦
    • 用户无需关注如何创建线程,如何调度线程来执行任务,用户只需提供Runnable对象,将任务的运行逻辑提交到执行器(Executor)中,由Executor框架完成线程的调配和任务的执行部分。
  • ExecutorService
    • 继承Executor的接口
    • 提供了更完善的生命周期管理能力,通过Future对象提供任务取消、状态查询、结果获取能力实现了任务监控。
  • AbstractExecutorService
    • 抽象类
    • 将执行任务的流程串联了起来,保证下层的实现只需关注一个执行任务的方法即可
  • ThreadPoolExecutor
    • 核心实现
    • 提供了高度可配置的线程池,允许我们精细控制线程池的各种行为
    • 一方面维护自身的生命周期,另一方面同时管理线程和任务,使两者良好的结合从而执行并行任务。
  • ScheduledThreadPoolExecutor
    • ScheduledExecutorService接口的实现类,继承ThreadPoolExecutor
    • 专门用于处理定时和周期任务
  • Executors
    • 一个静态工厂模式的工具类,提供了一系列静态方法来创建各种常见配置的线程池,简化了创建线程池的使用但是会带来一些问题,很多开发规范里都不建议大家直接使用。
    • 生产环境中建议谨慎使用或直接使用ThreadPoolExecutor构造函数自定义。

线程池原理

任务管理:

  • 任务调度
  • 任务缓冲。不同的队列可以实现不一样的任务存取策略。
  • 任务申请
  • 任务拒绝。JDK提供的四种已有拒绝策略

线程管理:

  • 创建
    • Worker这个工作线程,实现了Runnable接口。并持有一个线程thread,一个初始化的任务firstTask。
    • thread是在调用构造方法时通过ThreadFactory来创建的线程
    • firstTask。如果这个值是非空的,那么线程就会在启动初期立即执行这个任务,也就对应核心线程创建时的情况;如果这个值是null,那么就需要创建一个线程去执行任务列表(workQueue)中的任务,也就是非核心线程的创建。
  • 回收
    • 线程长时间不运行的时候进行回收。线程池使用一张Hash表去持有线程的引用,这样可以通过添加引用、移除引用这样的操作来控制线程的生命周期。将其引用消除可被JVM自动的回收。
    • Worker是通过继承AQS,使用AQS来实现独占锁这个功能。没有使用可重入锁ReentrantLock,而是使用AQS,为的就是实现不可重入的特性去反应线程现在的执行状态。
  • 增加
  • 执行
相关推荐
写后端的胖头鱼3 天前
如何区分IO/CPU 密集型,线程池核心参数怎么设置
java·线程池·多线程·io密集·cpu密集
随遇而安zx15 天前
【多线程】---线程池 ThreadPoolExecutor 原理与调优
java·线程池·多线程
ly768915 天前
Spring 异步编程的隐藏风险:@Async 线程池耗尽与异常处理详解
java·后端·spring·异常处理·线程池·任务拒绝
~木雨17 天前
Java 并发编程架构全景:并发层的五域设计 —— 线程模型、线程池隔离、并发安全到问题治理(全体系汇总)
java·安全·架构·线程池·并发编程·高并发架构
琥珀色糖17 天前
Linux手搓线程池!(C和C++版)
线程池
~木雨19 天前
Java 线程池七问七答:参数、执行流程、拒绝策略到 ThreadLocal 内存泄漏,面试必背
java·面试·线程池·threadlocal·threadpool·executor
小宇宙清歡渡23 天前
SpringBoot JDK17 线程池的使用
springboot·线程池·jdk17
AI人工智能+电脑小能手1 个月前
大白话说Java设计模式-37-中介者模式(源码剖析篇)
java·设计模式·线程池·中介者模式·源码分析·executor·applicationeventmulticaster
JacksonMx1 个月前
CompletableFuture 生产环境踩坑详解与解决方案
spring boot·spring·线程池
lisin-lee-cooper1 个月前
简单聊聊线程池源码
java·线程池