线程池

作者: caster | 来源:发表于2021-04-30 17:38 被阅读0次

1. 线程池原理

使用线程池的好处:

  • 重复利用线程,降低创建销毁线程开销,节约资源。
  • 重复利用线程,任务无需等待线程创建就立即执行,提高响应速度。
  • 重复利用线程,对线程进行统一管理维护,掌控线程资源。

线程池的基本实现
通过ThreadPoolExecutor类可以通过以下属性构造一个线程池:

构造函数成员变量 说明
corePoolSize 池中保留的核心线程数,即使空闲也保留,除非设置了allowCoreThreadTimeOut
maximumPoolSize 池中可放的最大线程数
keepAliveTime 当池中线程数量大于corePoolSize值时,空闲线程终止前等待新任务的最大时间
unit keepAliveTime的时间单位
workQueue 用来保存尚未执行的execute方法提交的Runnable 任务
threadFactory 用于创建工作线程worker的工厂
handler 当线程池和队列都满了需要进行的饱和策略,由4个内部类构成4中策略

ThreadPoolExecutor可用的workQueue为实现BlockingQueue接口的阻塞队列,可用以下几种队列(建议使用有界队列):

workQueue队列 说明
ArrayBlockingQueue 基于数组的有界阻塞队列,先进先出
LinkedBlockingQueue 基于链表的阻塞队列,先进先出,Executors.newFixedThreadPool()使用了此种队列
SynchronousQueue 不存储元素,每个插入操作都必须等待另一个线程执行相应的删除操作,否则插入操作一直阻塞,Executors.newCachedThreadPool() 使用了此种队列
PriorityBlockingQueue 具有优先级的无界阻塞队列

ThreadPoolExecutor中4种饱和策略类如下:

内部饱和策略处理类 说明
CallerRunsPolicy 调用当前线程池的所在的线程去执行被拒绝的任务,如果是主线程构造的线程池,会阻塞主线程
AbortPolicy 直接抛出异常
DiscardPolicy 不作处理,相当于直接丢弃当前任务
DiscardOldestPolicy 丢弃队列里面最近的任务,并execute当前任务

ThreadPoolExecutor类中其他重要的属性如下:

重要属性 说明
workers:HashSet<Worker> 内部类Worker的一个集合,Worker为线程池内的工作线程实现类,其run()方法会不断从workQueue 中获取任务来执行
ctl:AtomicInteger 包含了线程池的运行状态和worker线程个数
... ...

ThreadPoolExecutor类中重要的方法如下:

重要方法 说明
execute(Runnable) 添加一个任务到线程池,方法内会调用addWorker方法初始化或者扩充线程池的工作线程
addWorker(Runnable,boolean) 添加一个工作线程到线程池:参数1可以指派此线程的第一个任务,参数2指定范围是corePoolSize还是maximumPoolSize,超过范围直接返回false,创建失败
... ...

线程池处理任务的工作流程
线程池处理任务的流程即execute(Runnable)方法的流程,分为以下三步:

  • 当前运行线程小于corePoolSize,则以给定的任务为第一个任务创建一个新的核心线程(addWorker方法参数二设置为true)去处理此任务。
  • 将给定的任务添加到workQueue中,并进行双重检查确保线程池正常处理此任务。
  • 将任务指定给新的非核心线程去处理,如果超过maximumPoolSize值,则拒绝此任务交给RejectedExecutionHandler进行饱和策略处理。

线程池的状态
ctl属性中包含了线程池的状态信息,共以下四种:

线程池状态 说明
RUNNING 接受新的任务并处理workQueue中的任务
SHUTDOWN 不接受新的任务但处理workQueue中的任务
STOP 不接受新的任务且不处理workQueue中的任务(中断任务)
TIDYING 所有任务都结束,workerCount值为0,并运行terminated()方法
TERMINATED terminated()方法运行结束,线程池终止

状态转换流程如下图所示:


线程池运行状态转换流程

2. 线程池使用

创建线程池
提交任务
监控线程池
关闭线程池

3. 线程池框架

Executor是JDK5开始提供的线程执行机制框架,负责调控执行线程的工作单元Runnable和Callable。Executor框架组成如下如所示:


Executor框架组成
  • Executor: 提供Executor框架的核心接口execute(Runnable command),负责提交任务以备后续执行。
  • ExecutorService:提供三个submit接口以及线程池状态shutdown()等相关接口。
  • ThreadPoolExecutor:线程池核心实现类。
  • ScheduledThreadPoolExecutor:延时/定时型线程池实现类。
  • Executors:用来创建线程池的工厂类,可以创建三种类型的ThreadPoolExecutor线程池和两种类型ScheduledThreadPoolExecutor线程池,具体说明如下表:
ThreadPoolExecutor类线程池 说明
SingleThreadExecutor 单个线程的线程池,使用无界队列LinkedBlockingQueue
FixedThreadPool 固定线程数的线程池,使用无界队列LinkedBlockingQueue
CachedThreadPool 线程数量无界的线程池,使用无容量队列SynchronousQueue
  • ScheduledThreadPoolExecutor:此类线程池用于延时或者定时执行任务,使用自己子类DelayedWorkQueue作为任务队列,调用scheduleAtFixedRate()或者scheduleWithFixedDelay()会添加一个延时(定时)任务ScheduledFutureTask。
    ScheduledFutureTask的time变量为线程要执行的时间,当线程池workers获取到期要执行的任务执行完后,会将任务的time修改为下次要执行的时间重新放回队列。
ScheduledThreadPoolExecutor类线程池 说明
SingleThreadScheduledExecutor 单个线程的用于周期任务线的程池
ScheduledThreadPool 多个线程的用于多个周期任务线的程池
  • FutureTask:FutureTask实现了Runnable和Future接口,Future和FutureTask代表异步计算结果。

相关文章

  • java线程池

    线程VS线程池 普通线程使用 创建线程池 执行任务 执行完毕,释放线程对象 线程池 创建线程池 拿线程池线程去执行...

  • java----线程池

    什么是线程池 为什么要使用线程池 线程池的处理逻辑 如何使用线程池 如何合理配置线程池的大小 结语 什么是线程池 ...

  • Java线程池的使用

    线程类型: 固定线程 cached线程 定时线程 固定线程池使用 cache线程池使用 定时调度线程池使用

  • Spring Boot之ThreadPoolTaskExecut

    初始化线程池 corePoolSize 线程池维护线程的最少数量keepAliveSeconds 线程池维护线程...

  • 线程池

    1.线程池简介 1.1 线程池的概念 线程池就是首先创建一些线程,它们的集合称为线程池。使用线程池可以很好地提高性...

  • 多线程juc线程池

    java_basic juc线程池 创建线程池 handler是线程池拒绝策略 排队策略 线程池状态 RUNNIN...

  • ThreadPoolExecutor线程池原理以及源码分析

    线程池流程: 线程池核心类:ThreadPoolExecutor:普通的线程池ScheduledThreadPoo...

  • 线程池

    线程池 [TOC] 线程池概述 什么是线程池 为什么使用线程池 线程池的优势第一:降低资源消耗。通过重复利用已创建...

  • java 线程池使用和详解

    线程池的使用 构造方法 corePoolSize:线程池维护线程的最少数量 maximumPoolSize:线程池...

  • 线程池

    JDK线程池 为什么要用线程池 线程池为什么这么设计 线程池原理 核心线程是否能被回收 如何回收空闲线程 Tomc...

网友评论

      本文标题:线程池

      本文链接:https://www.haomeiwen.com/subject/njnohltx.html