Java多线程之Executor框架

文章目录

  • Executor框架
    • 一、Executor框架组成部分
    • 二、ThreadPoolExecutor核心参数
    • 三、线程池的生命周期
    • 四、四种线程池的创建方式
    • 五、线程池实现原理
    • 六、线程池4种拒绝策略

⭐️最全线程知识汇总篇(线程生命周期、线程池创建、线程池实现原理、线程基本方法)⭐️
⭐️ 如何创建一个线程?
⭐️ 线程生命周期及五种状态
⭐️ 多线程分批处理数据

Executor框架

Executor是一套线程池管理框架。是JDK 1.5中引入的一系列并发库中与Executor相关的功能类,其中最核心的类就是常见的ThreadPoolExecutor。

一、Executor框架组成部分

1、工作任务:就是Runnable/Callable接口的实现,可以被线程池执行;

2、异步计算结果:Future接口。实现Future接口的FutureTask类,代表异步处理结果;

3、 执行机制:

Executor接口:只有一个execute()方法;

ExecutorService接口:ExecutorService扩展了Executor接口,增加了生命周期的管理方法。
ExecutorService的生命周期包括三种状态:运行、关闭、终止。
创建后便进入运行状态,当调用了shutdown()方法时,便进入关闭状态,此时意味着ExecutorService不再接受新的任务,但它还在执行已经提交了submit()的任务,当已经提交了的任务执行完后,便到达终止状态。

ScheduledExecutorService接口:任务调度的线程池实现,可以在给定的延迟后运行命令或者定期执行命令;

ThreadPoolExecutor:最核心的线程池实现,用来执行被提交的任务;
Java多线程之Executor框架_第1张图片

二、ThreadPoolExecutor核心参数

Executor是线程池的顶级接口,接口中只定义了一个方法 void execute(Runnable command);线程池的操作方法都是定义子在ExecutorService子接口中的,所以说ExecutorService是线程池真正的接口。

ThreadPoolExecutor提供了四个构造方法,来看下重要参数:

public ThreadPoolExecutor(
int corePoolSize,
int maximumPoolSize,
long keepAliveTime,
TimeUnit unit,
BlockingQueue<Runnable> workQueue,
ThreadFactory threadFactory,
RejectedExecutionHandler handler) {}

参数含义如下:

  • corePoolSize:线程池核心线程数

  • maximumPoolSize:线程池最大数

  • keepAliveTime:空闲线程存活时间

  • unit:时间单位

  • workQueue:线程池所使用的缓冲队列

  • threadFactory:线程池创建线程使用的工厂

  • handler:线程池对拒绝任务的处理策略

三、线程池的生命周期

线程池的生命周期,总共有五种状态:

  • RUNNING(111) :能接受新提交的任务,并且也能处理阻塞队列中的任务;

  • SHUTDOWN(000):关闭状态,不再接受新提交的任务,但却可以继续处理阻塞队列中已保存的任务。在线程池处于 RUNNING 状态时,调用 shutdown()方法会使线程池进入到该状态。(finalize() 方法在执行过程中也会调用shutdown()方法进入该状态);

  • STOP(001):不能接受新任务,也不处理队列中的任务,会中断正在处理任务的线程。在线程池处于 RUNNING 或 SHUTDOWN 状态时,调用 shutdownNow() 方法会使线程池进入到该状态;

  • TIDYING(010):如果所有的任务都已终止了,workerCount (有效线程数) 为0,线程池进入该状态后会调用 terminated() 方法进入TERMINATED 状态。

  • TERMINATED(011):在terminated() 方法执行完后进入该状态,默认terminated()方法中什么也没有做。

ThreadPoolExecutor 使用int的高三位表示线程池状态,低29位表示线程数量;

Java多线程之Executor框架_第2张图片

四、四种线程池的创建方式

Executors类提供了一系列工厂方法用于创建线程池:

1、public static ExecutorService newFixedThreadPool(int nThreads)
创建固定数目线程的线程池。

2、public static ExecutorService newCachedThreadPool()
创建一个可缓存的线程池,调用execute将重用以前构造的线程(如果线程可用)。如果现有线程没有可用的,则创建一个新线 程并添加到池中。终止并从缓存中移除那些已有 60 秒钟未被使用的线程。

3、public static ExecutorService newSingleThreadExecutor()
创建一个单线程化的Executor。

4、public static ScheduledExecutorService newScheduledThreadPool(int corePoolSize)
创建一个支持定时及周期性的任务执行的线程池,多数情况下可用来替代Timer类。

五、线程池实现原理

1、如果运行线程数小于corePoolSize,那么马上创建线程运行这个任务;

2、如果正在运行的线程数大于等于corePoolSize,那么将这个任务放进队列;

3、如果队列放满了,如果正在运行的线程数小于maximumPoolSize,创建线程处理任务;

4、如果队列放满了,正在运行的线程数大于等于maximumPoolSize,那么线程会抛出异常;RejectExecutionException,执行拒绝策略。

Java多线程之Executor框架_第3张图片

六、线程池4种拒绝策略

1、AbortPolicy :直接抛出异常,阻止系统运行(线程池默认的拒绝策略);

2、CallerRunsPolicy:由调用线程处理;

3、DiscardPolicy:丢弃无法处理的任务,不予任何处理;

4、DiscardOldestPolicy:丢弃最老的一个请求,也就是即将被执行的一个任务,重新提交被拒绝的任务。

小结:Java线程池中两种提交任务的方法submit() 和 execute()有什么区别? 两个方法都可以向线程池提交任务,execute()方法的返回类型是void,它定义在Executor接口中。而submit()方法可以返回持有计算结果的Future对象,它定义在ExecutorService接口中,它扩展了Executor接口,其它线程池类像ThreadPoolExecutor和ScheduledThreadPoolExecutor都有这些方法。

你可能感兴趣的:(《Java高并发编程》系列,java,线程池,并发编程)