Java 线程池及线程池状态

Java 中的线程池
  • 什么是线程池
    • 线程池(ThreadPool)是一种基于池化思想管理和使用线程的机制,它是将多个线程预先存储在一个池子内,当有任务出现时可以避免重新创建和销毁线程所带来性能开销,只需要从池子内取出相应的线程执行对应的任务即可

  • 线程池的创建方法总共有 7 种,但总体来说可分为 2 类:
    • 一类是通过 ThreadPoolExecutor 创建的线程池
    • 另一个类是通过 Executors 创建的线程池 ( [Java开发手册] 规范不允许使用)

  • 线程池的创建方式总共包含以下 7 种(其中 6 种是通过 Executors 创建的,1 种是通过 ThreadPoolExecutor 创建的)
    • Executors.newFixedThreadPool:创建一个固定大小的线程池,可控制并发的线程数,超出的线程会在队列中等待
    • Executors.newCachedThreadPool:创建一个可缓存的线程池,若线程数超过处理所需,缓存一段时间后会回收,若线程数不够,则新建线程
    • Executors.newSingleThreadExecutor:创建单个线程数的线程池,它可以保证先进先出的执行顺序
    • Executors.newScheduledThreadPool:创建一个可以执行延迟任务的线程池
    • Executors.newSingleThreadScheduledExecutor:创建一个单线程的可以执行延迟任务的线程池
    • Executors.newWorkStealingPool:创建一个抢占式执行的线程池(任务执行顺序不确定,,JDK 1.8 添加
    • ThreadPoolExecutor:最原始的创建线程池的方式,它包含了 7 个参数可供设置,后面会详细讲

  • 单线程池的意义从以上代码可以看出 newSingleThreadExecutor 和 newSingleThreadScheduledExecutor 创建的都是单线程池,那么单线程池的意义是什么
    • 虽然是单线程池,但提供了工作队列,生命周期管理,工作线程维护等功能

  • ThreadPoolExecutor 参数介绍
    • public ThreadPoolExecutor(int corePoolSize,
                   int maximumPoolSize,
                  long keepAliveTime,
                  TimeUnit unit,
                  BlockingQueue workQueue,
                  ThreadFactory threadFactory,
                  RejectedExecutionHandler handler) {
      // 省略…
      }

    • corePoolSize:核心线程数,线程池中始终存活的线程数

    • maximumPoolSize:最大线程数,线程池中允许的最大线程数,当线程池的任务队列满了之后可以创建的最大线程数

    • keepAliveTime:最大线程数可以存活的时间,当线程中没有任务执行时,最大线程就会销毁一部分,最终保持核心线程数量的线程

    • unit: 单位是和参数 3 存活时间配合使用的,合在一起用于设定线程的存活时间 ,参数 keepAliveTime 的时间单位有以下 7 种可选:

      • TimeUnit.DAYS:天
      • TimeUnit.HOURS:小时
      • TimeUnit.MINUTES:分
      • TimeUnit.SECONDS:秒
      • TimeUnit.MILLISECONDS:毫秒
      • TimeUnit.MICROSECONDS:微妙
      • TimeUnit.NANOSECONDS:纳秒
    • workQueue:一个阻塞队列,用来存储线程池等待执行的任务,均为线程安全,它包含以下 7 种类型:

      • ArrayBlockingQueue:一个由数组结构组成的有界阻塞队列
      • LinkedBlockingQueue:一个由链表结构组成的有界阻塞队列
      • SynchronousQueue:一个不存储元素的阻塞队列,即直接提交给线程不保持它们
      • PriorityBlockingQueue:一个支持优先级排序的无界阻塞队列
      • DelayQueue:一个使用优先级队列实现的无界阻塞队列,只有在延迟期满时才能从中提取元素
      • LinkedTransferQueue:一个由链表结构组成的无界阻塞队列,与 SynchronousQueue 类似,还含有非阻塞方法
      • LinkedBlockingDeque:一个由链表结构组成的双向阻塞队列
        较常用的是 LinkedBlockingQueue 和 Synchronous,线程池的排队策略与 BlockingQueue 有关
    • threadFactory:线程工厂,主要用来创建线程,默认为正常优先级、非守护线程

    • handler:拒绝策略,表示当队列满了并且工作线程大于等于线程池的最大线程数(maximumPoolSize)时如何拒绝,系统提供了 4 种可选:

      • AbortPolicy:拒绝并抛出异常
      • CallerRunsPolicy:使用当前调用的线程来执行此任务
      • DiscardOldestPolicy:抛弃队列头部(最旧)的一个任务,并执行当前任务
      • DiscardPolicy:忽略并抛弃当前任务
        默认策略为 AbortPolicy

  • ThreadPoolExecutor 关键节点的执行流程如下:
Java 线程池及线程池状态_第1张图片

Java 中线程池状态
  • 线程池总共存在 5 种状态,定义在 ThreadPoolExecutor 类中,代码如下
public class ThreadPoolExecutor extends AbstractExecutorService {
    private static final int RUNNING    = -1 << COUNT_BITS;
    private static final int SHUTDOWN   =  0 << COUNT_BITS;
    private static final int STOP       =  1 << COUNT_BITS;
    private static final int TIDYING    =  2 << COUNT_BITS;
    private static final int TERMINATED =  3 << COUNT_BITS;
}
  • 线程池的5种状态具体如下
    • RUNNING:线程池创建之后的初始状态,这种状态下可以执行任务
    • SHUTDOWN:该状态下线程池不再接受新任务,但是会将工作队列中的任务执行完毕
    • STOP:该状态下线程池不再接受新任务,也不会处理工作队列中的剩余任务,并且将会中断所有工作线程
    • TIDYING:该状态下所有任务都已终止或者处理完成,将会执行 terminated() 钩子方法
    • TERMINATED:执行完 terminated() 钩子方法之后的状态。terminated 钩子方法在 Executor 终止时调用,默认实现不执行任何操作

  • 线程池的状态转换规则为:
    • 线程池创建之后状态为 RUNNING
    • 执行线程池的 shutdown() 实例方法,会使线程池状态从 RUNNING 转变为 SHUTDOWN
    • 执行线程池的 shutdownNow() 实例方法,会使线程池状态从 RUNNING 转变为 STOP
    • 当线程池处于 SHUTDOWN 状态时,执行其 shutdownNow() 方法会将其状态转变为 STOP
    • 等待线程池的所有工作线程停止,工作队列清空之后,线程池状态会从 STOP 转变为 TIDYING
    • 执行完 terminated() 钩子方法之后,线程池状态从 TIDYING 转变为 TERMINATED

你可能感兴趣的:(Java,java)