Java学习--线程池

1. 线程池概述

线程池是一种管理线程的机制,通过预先创建一定数量的线程来执行任务,避免频繁地创建和销毁线程,进而提高系统性能,减少资源消耗。线程池在程序启动时创建若干线程,当有任务提交时,线程池分配空闲线程来执行任务。线程池的好处包括减少线程创建的开销、提高响应速度以及限制最大并发数,从而有效控制资源使用。

2. 线程状态介绍

Java 中的线程状态被定义在 java.lang.Thread.State 枚举类中,包含六种状态:

线程状态 含义
NEW 线程刚被创建,但尚未启动。
RUNNABLE 线程已启动,具备执行资格,但正在等待 CPU 分配执行权。
BLOCKED 线程尝试获取一个被其他线程占用的锁时进入此状态。
WAITING 线程在等待其他线程的特定操作(如 wait()join())。
TIMED_WAITING 线程在有限时间内等待特定操作(如 sleep()wait(long))。
TERMINATED 线程已完成执行,进入终止状态。

3. 线程池的基本原理

线程池的核心思想是:预先创建多个线程,这些线程在任务到来时执行任务,任务执行完毕后线程返回池中等待下一个任务。线程池的设计思路如下:

  1. 准备一个任务队列。
  2. 一次性启动多个消费者线程。
  3. 消费者线程开始等待任务的到来。
  4. 当任务加入队列时,线程池唤醒一个消费者线程执行任务。
  5. 任务执行完毕后,线程回到线程池中等待下一个任务。

4. 使用 Executors 创建线程池

Java 提供了 Executors 工具类用于创建线程池,常见的线程池类型有:

4.1 newCachedThreadPool()

创建一个默认线程池,线程池中的线程数量动态增长。适合执行短时间内大量请求的场景。

ExecutorService executorService = Executors.newCachedThreadPool();

4.2 newFixedThreadPool(int nThreads)

创建一个固定大小的线程池,适合处理固定数量并发任务的场景。

ExecutorService executorService = Executors.newFixedThreadPool(10);

4.3 newSingleThreadExecutor()

创建一个单线程池,适用于需要顺序执行任务的场景。

ExecutorService singleThreadExecutor = Executors.newSingleThreadExecutor();

4.4 newScheduledThreadPool(int nThreads)

创建一个支持定时或周期性任务的线程池。

ScheduledExecutorService scheduledThreadPool = Executors.newScheduledThreadPool(5);

5. 自定义线程池 ThreadPoolExecutor

除了使用 Executors 创建线程池外,我们还可以通过 ThreadPoolExecutor 自定义线程池。

构造方法:

ThreadPoolExecutor pool = new ThreadPoolExecutor(
    核心线程数, 最大线程数, 空闲线程存活时间, 时间单位, 任务队列, 创建线程工厂, 拒绝策略);

示例代码:

ThreadPoolExecutor pool = new ThreadPoolExecutor(
    2, 5, 2, TimeUnit.SECONDS,
    new ArrayBlockingQueue<>(10),
    Executors.defaultThreadFactory(),
    new ThreadPoolExecutor.AbortPolicy());

6. 线程池参数详解

  • corePoolSize:核心线程数,线程池中始终保持存活的线程数量。
  • maximumPoolSize:最大线程数,线程池中能够存在的最大线程数量。
  • keepAliveTime:空闲线程的最大存活时间。
  • unit:时间单位,配合 keepAliveTime 使用。
  • workQueue:任务队列,用于存储等待执行的任务。
  • threadFactory:线程工厂,用于创建线程。
  • handler:任务拒绝策略,当任务队列满时执行的策略。

7. 线程池的任务拒绝策略

线程池提供了四种任务拒绝策略,当线程池和队列已满时执行:

  1. AbortPolicy(默认):直接抛出 RejectedExecutionException 异常,丢弃任务。
  2. DiscardPolicy:直接丢弃任务,不抛出异常。
  3. DiscardOldestPolicy:丢弃队列中等待时间最久的任务,执行当前任务。
  4. CallerRunsPolicy:调用任务的线程执行任务,绕过线程池。

示例代码展示了不同策略的使用和对应的行为。

8. 总结

线程池是多线程编程中的关键工具,合理地使用线程池可以提高程序的并发处理能力,优化资源利用率。Java 提供了 Executors 工具类来方便地创建不同类型的线程池,同时也可以通过 ThreadPoolExecutor 进行自定义,满足更多应用场景需求。掌握线程池的使用对于写出高效的多线程程序非常重要。

你可能感兴趣的:(java,学习,开发语言)