线程池

线程池

简介

缓存已创建的线程,以备执行后续的任务。

目的:
创建和销毁消除消耗系统的资源,通过缓存已创建的线程,避免频繁的创建线程,从而减少系统的消耗。


与线程池有关的类和接口

  • Executor :底层接口,定义了 execute() ,表示执行传进来的任务。
  • ExecutorService :继承自 Executor ,声明了一些常用方法: submit , invokeAll , invokeAny , shutDown 。
  • AbstractExecutorService :实现 ExecutorService 接口,基本实现 ExecutorService 中的方法。
  • ThreadPoolExecutor :继承自 AbstractExecutorService 。 execute() :向线程池提交一个任务,由线程池执行。 submit() :向线程池提交任务,可以返回任务执行的结果。 shutdown() 关闭线程。 shutdownNow() :立即关闭线程池。

线程池的参数

  • corePoolSize :核心池的大小。创建线程池默认没有线程,得到任务到达时才创建线程。当线程数目到达 corePoolSize 时,会把后续的任务放入缓存队列中。
  • maximumPoolSize :线程池的最大线程数。表示线程池中所能容纳的最大的线程数量。
  • keepAliveTime :表示线程在没有执行任务,存活多久后被终止。当线程池中的线程大于 corePoolSize 时,会对超过数量的线程统计空闲时间,然后超过 keepAliveTime 的线程会被终止,直到线程池中的线程数量不超过 corePoolSize 。
  • unit :超时时间单位。
  • workQueue :阻塞队列,用来存储等待执行的任务。
  • threadFactory :线程工厂,创建一个新线程时使用的工厂,可以设定线程名,是否为守护线程。
  • handler :拒绝策略,当等待队列中的任务达到最大限制,并且线程池中线程数达到最大限制时,若有新的任务到达,则采取的拒绝策略。

线程池的状态

  • RUNNING = 0 :线程池创建完后初始化。
  • SHUTDOWN = 1 :调用 shutdown() 方法,线程池不再接受新的任务,等待现有任务执行完。
  • STOP = 2 :调用 shutdownNow() 方法,线程池不接受新的任务,并且终止正在执行的任务。
  • TERMINATED = 3 :线程池处于SHUTDOWN或STOP状态,并且工作线程已被销毁,任务队列已被清空,则进入TERMINATED状态。

线程池执行流程

流程:

  1. 如果当前线程池中的线程数目 小于  < corePoolSize 。则对于每个新任务,都会创建一个线程去执行这个任务。
  2. 如果当前线程池中的线程数目 大于等于 >= corePoolSize 。对于每个新任务,会将其添加到任务队列中。若添加成功,则任务由空闲的线程主动将其从队列中移除后执行。若添加失败(任务队列已满),则尝试创建新的线程执行。
  3. 若当前线程池中的线程数目到达 maximumPoolSize ,则对于新任务采取拒绝策略。
  4. 如果线程池中的数量大于 corePoolSize 时,如果某个线程空闲时间超过 keepAliveTime ,线程会被终止,直到线程池中的线程数目不超过 corePoolSize 。
  5. 如果为核心线程池中的线程设置存活时间,则当核心线程池中的线程空闲时间超过 keepAliveTime ,则该线程也会被终止。

线程池的初始化

  • 默认情况下,创建线程池后,线程池中没有线程。需要在提交任务后才创建线程。
  • 可以通过两个方法在创建线程池后创建线程:
    • prestartCoreThread() :初始化一个线程。
    • prestartAllCoreThread():初始化所有核心线程。

任务队列和排队策略

workQueue :用来存放等待执行的任务。类型为 BlockingQueue<Runnable> 。

阻塞队列

分类:

  • FIFO:先进先出。先进入队列中的元素最先出队列。
  • LIFO:先进后出。后进入队列的元素最先出队列。

操作

  • 插入 :当队列已满时,生产者线程插入数据会被阻塞,直到消费者消耗队列中的数据使得队列有空闲空间。
  • 获取 :当队列为空时,消费者线程获取数据时会被阻塞,直到生产者向队列中插入数据。

方法

  • 插入数据:
    • offer() :添加数据成功返回true,添加失败返回false。(若没有设置超时时间,则直接返回;若设置超时时间,则等待指定的超时时间,超时时间过期后返回false)
    • put() :添加数据成功则直接返回,添加失败会被一直阻塞。
  • 获取数据:
    • poll() :若队列有元素,则获取队首元素;否则直接返回null。(若设置超时时间,则未成功获取元素时阻塞等待,直到超时返回null或成功获取元素)
    • take() :若队列非空,则直接返回队列首部元素;否则一直阻塞,直到成功获取元素或被中断。

类型:

  • ArrayBlockingQueue :基于 数组 的FIFO队列,创建时必须指定大小,内部使用定长数组缓存数据。读写数据同用同一个锁对象(可以使用锁分离实现生产者和消费者的并行,但 ArrayBlockingQueue 的读写为轻量级,使用锁分离只会增加复杂度。),可以采用公平锁或非公平锁。
  • LinkedBlockingQueue :基于 链表 的FIFO队列,可以不指定大小,则大小为 Integer.MAX_VALUE 。对于生产者和消费者采用独立的锁进行同步,生产者和消费者可以并发操作队列中的数据。(若没有设置初始容量可能由于线程过多导致内存耗尽)
  • synchronousQueue :一种没有缓冲的等待队列。不保存提交的任务,而是直接创建一个新线程执行新的任务。
    • 若为 公平模式 :采用公平锁,并使用FIFO队列阻塞生产者和消费者。
    • 若为 非公平模式 :采用非公平锁,使用LIFO队列管理阻塞的生产者和消费者。
  • DelayQueue :队列中元素只有在指定的延迟时间到了才能获取到。生产者线程不会被阻塞,消费者线程在队列为空或者没有元素到期时会被阻塞。
  • PriorityBlockingQueue :基于优先级的阻塞队列。不会阻塞生产者。当队列中没有元素时,阻塞消费者。采用公平锁。

拒绝策略

情景

当线程池中的线程达到 maximumPoolSize ,并且任务队列已满,此时对于新来的任务采取拒绝策略进行处理。

分类

  • AbortPolicy :抛弃任务,并抛出异常。
  • DiscardPolicy :直接抛弃任务,但不抛出异常。
  • DiscardOldPolicy :抛弃任务队列中最前的任务(最老的任务),然后尝试执行新任务。
  • CallerRunPolicy :由调用线程处理任务。

线程池的关闭

  • shutdown() :不会立即终止线程池,而是不再接受新的任务,并且等待所有任务缓存队列中的任务都执行完后才终止。
  • shutdownNow() :立即终止线程池,并打断正在执行的任务,清空任务队列,返回尚未执行的任务。

线程池容量的动态调整

  • setCorePoolSize() :设置核心池的大小。
  • setMaximumPoolSize() :设置线程池最大能创建线程的数目。

配置线程池的参数

根据任务的类型进行配置。

  • CPU密集型任务: corePoolSize 设置为CPU核心数+1;
  • IO密集型任务: corePoolSize 设置为2*CPU核心数。

Executors 创建四种线程池

提供一系列工厂方法来创建线程池。

  • newCachedThreadPool :一个可缓存线程池,通过 execute 重用已经构建的线程。若没有可用线程,则创建新线程并添加到线程池中。终止超时未使用(60s)的线程。
  • newFixedThreadPool :一个固定线程数量的线程池,控制线程的最大并发数,超过的线程在队列中等待。
  • newScheduledThreadPool :一个定长的线程池,支持定时以及周期性任务执行。
  • newSingleThreadExecutor :一个单线程的线程池,使用一个工作线程,保证任务按照FIFO,LIFO顺序执行。

newCachedThreadPool

  • 先查看线程池中有没有已创建的线程,若有,则进行复用;否则创建一个新的线程加入池中。
  • 适用于 执行周期短的异步任务 。
  • 超时没有被使用的线程会被终止。

newFixedThreadPool

  • 任意时刻只有固定数量的活动线程存在。
  • 没有可用的线程时,新来的任务会被放入等待队列中。

newScheduledThreadPool

  • 有两种定期执行任务:
    • 固定延迟执行:当前一个任务执行完成后,固定时延后执行新的任务。
    • 固定频率执行:当前一个任务执行时,固定时延后执行,不管前一个任务是否执行完成。

newSingleThreadExecutor

  • 单例线程池,任意时刻只有一个线程。
原文地址:https://www.cnblogs.com/truestoriesavici01/p/13662895.html