Wrayの知识库 Wrayの知识库
首页
  • Java 基础
  • Java 集合
  • Java 并发
  • Java IO
  • JVM
  • Spring Framework
  • Spring Boot
  • Spring Cloud
  • Spring Security
  • MySQL
  • Redis
  • MacOS
  • Linux
  • Windows
  • 纸质书
  • 电子书
  • 学习课程
疑难杂症
GitHub (opens new window)
首页
  • Java 基础
  • Java 集合
  • Java 并发
  • Java IO
  • JVM
  • Spring Framework
  • Spring Boot
  • Spring Cloud
  • Spring Security
  • MySQL
  • Redis
  • MacOS
  • Linux
  • Windows
  • 纸质书
  • 电子书
  • 学习课程
疑难杂症
GitHub (opens new window)
  • Java基础

    • Java概述
    • Java语法
    • 面向对象编程
    • Java数组
    • String字符串
    • 异常处理
  • Java集合

    • Java集合概述
    • ArrayList
    • LinkedList
    • HashMap
    • LinkedHashMap
    • HashSet
    • TreeMap
    • Queue&Deque
  • Java并发

    • Java并发概述
    • 线程与进程
    • Thread类与线程生命周期
    • 线程安全
    • synchronized关键字
    • volatile关键字
    • Java内存模型(JMM)
    • 线程间通信
    • 线程池
      • 1. 为什么需要线程池
      • 2. 线程池的核心组成
      • 3. 常见的线程池类型
      • 4. ThreadPoolExecutor 的工作流程
      • 5. 线程池的拒绝策略
      • 6. 线程池的生命周期
      • 7. 使用线程池的最佳实践
      • 8. 线程池的实际应用场景
      • 9. 总结
    • 并发工具类
    • 原子操作类Atomic
    • 并发锁
    • 并发容器
    • ConcurrentHashMap
    • BlockingQueue
    • CopyOnWriteArrayList
    • ThreadLocal
    • Fork/Join框架
    • ScheduledThreadPoolExecutor
    • CompletableFuture
  • Java IO

    • Java IO概述
  • JVM

    • JVM概述
  • Java
  • Java并发
Wray
2024-10-31
目录

线程池

线程池是 Java 并发编程中非常重要的一个工具,它用于管理一组工作线程的创建和调度,减少线程创建和销毁的开销,提高系统性能和响应速度。Java 提供了丰富的线程池支持,特别是在 java.util.concurrent 包中,通过线程池可以更高效地管理和复用线程资源。

# 1. 为什么需要线程池

  • 减少性能开销:线程的创建和销毁是比较昂贵的操作,频繁创建和销毁线程会严重影响系统性能。线程池通过复用已有的线程,避免了这种开销。
  • 控制线程数量:在大型系统中,过多的线程会导致系统资源耗尽,线程池可以限制线程数量,防止因线程过多导致的资源竞争。
  • 提高响应速度:线程池可以在接收到任务时,立即复用已有的线程,从而缩短任务的等待时间,提高系统响应速度。

# 2. 线程池的核心组成

Java 线程池的核心类是 ThreadPoolExecutor,它的工作原理主要涉及以下几个核心组成部分:

  • 核心线程数(corePoolSize):核心线程的数量,即线程池中始终存活的最小线程数。
  • 最大线程数(maximumPoolSize):线程池中允许的最大线程数,当任务较多时会增加线程到最大线程数。
  • 工作队列(workQueue):用于保存等待执行任务的队列。当所有核心线程都在忙碌时,新任务会进入队列排队等待。
  • 线程工厂(ThreadFactory):用于创建新线程,通常用于设置线程名、优先级等属性。
  • 拒绝策略(RejectedExecutionHandler):当任务无法提交到线程池时的处理策略,例如丢弃任务、抛出异常等。

# 3. 常见的线程池类型

Java 提供了 Executors 工具类,用于创建不同类型的线程池,主要有以下几种:

  • newFixedThreadPool(int nThreads):

    • 创建一个固定大小的线程池,线程池中始终有指定数量的线程数,适用于需要限制线程数量以应对突发任务的场景。
  • newCachedThreadPool():

    • 创建一个可缓存的线程池,线程池会根据需要动态创建线程,适用于执行短期异步任务的场景。如果线程空闲超过 60 秒会被回收。
  • newSingleThreadExecutor():

    • 创建一个只有一个线程的线程池,保证所有任务按照顺序逐一执行,适用于需要按顺序执行任务的场景。
  • newScheduledThreadPool(int corePoolSize):

    • 创建一个线程池,可以定期或延时执行任务,适用于需要周期性任务的场景,例如定时备份、日志处理等。

# 4. ThreadPoolExecutor 的工作流程

当一个任务被提交到线程池时,ThreadPoolExecutor 的工作流程如下:

  1. 检查核心线程数:如果当前运行的线程数少于核心线程数,则创建一个新线程来执行任务。
  2. 任务入队:如果当前线程数等于核心线程数,则将任务加入工作队列。
  3. 创建非核心线程:如果工作队列已满,并且当前线程数小于最大线程数,则创建新的非核心线程来处理任务。
  4. 拒绝任务:如果线程数达到了最大线程数,并且工作队列也已满,则执行拒绝策略。

# 5. 线程池的拒绝策略

ThreadPoolExecutor 提供了 4 种拒绝策略,位于 RejectedExecutionHandler 接口中:

  • AbortPolicy(默认策略):抛出 RejectedExecutionException 异常,阻止任务执行。
  • CallerRunsPolicy:由提交任务的线程(通常是主线程)来执行该任务。
  • DiscardPolicy:直接丢弃无法处理的任务,不抛出异常。
  • DiscardOldestPolicy:丢弃队列中最老的任务,然后尝试重新提交当前任务。

# 6. 线程池的生命周期

线程池的生命周期主要包括以下几个状态:

  • RUNNING:线程池可以接受新任务并处理已加入的任务。
  • SHUTDOWN:调用 shutdown() 方法后,线程池不再接受新任务,但会继续处理已加入的任务。
  • STOP:调用 shutdownNow() 方法后,线程池不再接受新任务,并尝试停止正在执行的任务。
  • TIDYING:所有任务已终止,线程池中的线程数为 0,进入 TIDYING 状态。
  • TERMINATED:terminated() 方法执行完毕后,线程池进入终止状态。

# 7. 使用线程池的最佳实践

  • 合理配置线程池大小:线程池的大小应该根据具体的任务类型和系统资源配置来确定。可以使用 CPU 密集型 或 IO 密集型 的策略来合理配置线程池的核心线程数。

    • CPU 密集型任务:线程数一般为 CPU 核心数 + 1。
    • IO 密集型任务:线程数应该远大于 CPU 核心数,一般为 CPU 核心数的几倍。
  • 避免使用 Executors 创建线程池:Executors 工具类虽然方便,但可能会隐藏一些问题,例如 newCachedThreadPool() 和 newFixedThreadPool() 默认的队列长度为 Integer.MAX_VALUE,可能会导致内存不足。因此推荐手动创建 ThreadPoolExecutor 并设置合理的参数。

  • 监控线程池状态:定期监控线程池的运行情况,如线程数、队列长度、任务完成情况等,可以及时发现问题并优化线程池配置。

# 8. 线程池的实际应用场景

  • Web 服务器:在 Web 服务器中,线程池可以用于处理并发的 HTTP 请求,提高服务器的吞吐量。
  • 异步任务处理:线程池可以用于执行异步任务,例如日志处理、文件上传等,避免阻塞主线程。
  • 周期性任务:使用 ScheduledThreadPoolExecutor 可以实现周期性任务调度,例如定时清理缓存、监控系统状态等。

# 9. 总结

线程池是 Java 并发编程中用于管理和复用线程的强大工具,通过线程池可以减少线程创建和销毁的开销,控制线程的数量,提升系统性能。理解线程池的工作原理、合理配置线程池大小、以及选择合适的线程池类型,是编写高效并发程序的关键。Java 提供的 ThreadPoolExecutor 及其他线程池实现为开发者提供了丰富的工具来应对各种并发场景。

上次更新: 2024/11/01, 13:45:14
线程间通信
并发工具类

← 线程间通信 并发工具类→

Copyright © 2023-2024 Wray | 鄂ICP备2024050235号-1
  • 跟随系统
  • 浅色模式
  • 深色模式
  • 阅读模式