JUC源码分析-线程池篇(三)ScheduledThreadPoolExecutor

ScheduledThreadPoolExecutor 继承自 ThreadPoolExecutor。它主要用来在给定的延迟之后运行任务,或者定期执行任务。ScheduledThreadPoolExecutor 的功能与 Timer 类似,但 Timer 对应的是单个后台线程,而 ScheduledThreadPoolExecutor 可以在构造函数中指定多个对应的后台线程数。

  1. JUC源码分析-线程池篇(三)Timer

1. ScheduledThreadPoolExecutor 简介

1.1 Timer 和 ScheduledThreadPoolExecutor 区别

Timer ScheduledThreadPoolExecutor
单线程 多线程
单个任务执行时间影响其他任务调度 多线程,不会影响
基于绝对时间 基于相对时间
一旦执行任务出现异常不会捕获,其他任务得不到执行 多线程,单个任务的执行不会影响其他线程

1.2 ScheduledThreadPoolExecutor 执行流程

ScheduledThreadPoolExecutor 的结构和 Timer 类似,也是由 DelayedWorkQueue、ThreadPoolExecutor、ScheduledFutureTask 三部分组成。DelayedWorkQueue 是一个无界队列,所以 ThreadPoolExecutor 的 maximumPoolSize 在 ScheduledThreadPoolExecutor 中没有什么意义(设置 maximumPoolSize 的大小没有什么效果)。

ScheduledThreadPoolExecutor 的执行主要分为两大部分。

1)当调用 ScheduledThreadPoolExecutor#scheduleAtFixedRate() 方法或者 scheduleWithFixedDelay() 方法时,会向 ScheduledThreadPoolExecutor#DelayedWorkQueue 添加一个实现了 RunnableScheduledFutur 接口的 ScheduledFutureTask。

2)线程池中的线程从 DelayedWorkQueue 中获取 ScheduledFutureTask,然后执行任务。

2. ScheduledThreadPoolExecutor 源码分析

2.1 数据结构

2.2 定时任务调度 schedule

schedule、scheduleAtFixedRate、scheduleWithFixedDelay 只是将任务设置执行时间后添加到线程池队列中去了。

ublic ScheduledFuture<?> scheduleAtFixedRate(Runnable command,
long initialDelay, long period, TimeUnit unit) {
if (command == null || unit == null)
throw new NullPointerException();
if (period <= 0)
throw new IllegalArgumentException();
ScheduledFutureTask<Void> sft =
new ScheduledFutureTask<Void>(command, null,
triggerTime(initialDelay, unit), unit.toNanos(period));
RunnableScheduledFuture<Void> t = decorateTask(command, sft);
sft.outerTask = t;
delayedExecute(t);
return t;
} public ScheduledFuture<?> scheduleWithFixedDelay(Runnable command,
long initialDelay, long delay, TimeUnit unit) {
if (command == null || unit == null)
throw new NullPointerException();
if (delay <= 0)
throw new IllegalArgumentException();
ScheduledFutureTask<Void> sft =
new ScheduledFutureTask<Void>(command, null,
triggerTime(initialDelay, unit), unit.toNanos(-delay));
RunnableScheduledFuture<Void> t = decorateTask(command, sft);
sft.outerTask = t;
delayedExecute(t);
return t;
}

2.3 任务执行 ScheduledFutureTask#run

public void run() {
boolean periodic = isPeriodic();
if (!canRunInCurrentRunState(periodic)) // 线程池关闭时是否断续执行定时任务
cancel(false);
else if (!periodic) // 只执行一次
ScheduledFutureTask.super.run();
else if (ScheduledFutureTask.super.runAndReset()) { // 周期性执行
setNextRunTime(); // 下一次执行时间
reExecutePeriodic(outerTask); // 重新添加到任务队列中
}
}

参考:

  1. 《深入理解Java线程池:ScheduledThreadPoolExecutor》:https://www.jianshu.com/p/925dba9f5969

每天用心记录一点点。内容也许不重要,但习惯很重要!

JUC源码分析-线程池篇(三)ScheduledThreadPoolExecutor的更多相关文章

  1. JUC源码分析-线程池篇(三)Timer

    JUC源码分析-线程池篇(三)Timer Timer 是 java.util 包提供的一个定时任务调度器,在主线程之外起一个单独的线程执行指定的计划任务,可以指定执行一次或者反复执行多次. 1. Ti ...

  2. JUC源码分析-线程池篇(一):ThreadPoolExecutor

    JUC源码分析-线程池篇(一):ThreadPoolExecutor Java 中的线程池是运用场景最多的并发框架,几乎所有需要异步或并发执行任务的程序都可以使用线程池.在开发过程中,合理地使用线程池 ...

  3. JUC源码分析-线程池篇(二)FutureTask

    JUC源码分析-线程池篇(二)FutureTask JDK5 之后提供了 Callable 和 Future 接口,通过它们就可以在任务执行完毕之后得到任务的执行结果.本文从源代码角度分析下具体的实现 ...

  4. Elasticsearch源码分析—线程池(十一) ——就是从队列里处理请求

    Elasticsearch源码分析—线程池(十一) 转自:https://www.felayman.com/articles/2017/11/10/1510291570687.html 线程池 每个节 ...

  5. 鸿蒙内核源码分析(线程概念篇) | 是谁在不停的折腾CPU? | 百篇博客分析OpenHarmony源码 | v21.06

    百篇博客系列篇.本篇为: v21.xx 鸿蒙内核源码分析(线程概念篇) | 是谁在不断的折腾CPU | 51.c.h .o 任务管理相关篇为: v03.xx 鸿蒙内核源码分析(时钟任务篇) | 触发调 ...

  6. nginx源码分析线程池详解

    nginx源码分析线程池详解 一.前言     nginx是采用多进程模型,master和worker之间主要通过pipe管道的方式进行通信,多进程的优势就在于各个进程互不影响.但是经常会有人问道,n ...

  7. nginx源码分析——线程池

    源码: nginx 1.13.0-release   一.前言      nginx是采用多进程模型,master和worker之间主要通过pipe管道的方式进行通信,多进程的优势就在于各个进程互不影 ...

  8. 鸿蒙内核源码分析(调度机制篇) | 任务是如何被调度执行的 | 百篇博客分析OpenHarmony源码 | v7.07

    百篇博客系列篇.本篇为: v07.xx 鸿蒙内核源码分析(调度机制篇) | 任务是如何被调度执行的 | 51.c.h .o 任务管理相关篇为: v03.xx 鸿蒙内核源码分析(时钟任务篇) | 触发调 ...

  9. 鸿蒙内核源码分析(时钟任务篇) | 触发调度谁的贡献最大 | 百篇博客分析OpenHarmony源码 | v3.05

    百篇博客系列篇.本篇为: v03.xx 鸿蒙内核源码分析(时钟任务篇) | 触发调度谁的贡献最大 | 51.c.h .o 任务管理相关篇为: v03.xx 鸿蒙内核源码分析(时钟任务篇) | 触发调度 ...

随机推荐

  1. linux(Ubuntu) 搭建LAMP环境

    1.更新源 sudo apt- get update 2.安装常用软件 SSH.Vim.Git.Tree ①SSH sudo apt-get install openssh-server 管理命令:s ...

  2. Pandas DataFrame操作

    DataFrame的创建 >>> import pandas as pd >>> from pandas import DataFrame #define a di ...

  3. 第一记 搭建Java集成开发环境

    一.JDK JDK可以前往oracle官网进行下载并进行安装(我这边使用的是jdk1.8版本,也推荐使用jdk1.8及以上的) 下图是默认路径安装完成后的截图 安装完成会产生这两个文件夹 二.配置环境 ...

  4. redis 入门之string

    set  用法 #set key value 设置value为字符串的键值对redis> SET key "value" #对不存在的key设置value OK redis& ...

  5. MyBatis笔记一:GettingStart

    MyBatis笔记一:GettingStart 1.MyBatis优点 我们的工具和各种框架的作用就是为了我们操作数据库简洁,对于一些数据库的工具能帮我们少写一些处理异常等等的代码,但是他们并不是自动 ...

  6. shell数组变量

  7. Android应用图标尺寸规范(转)

    转自:http://blog.sina.com.cn/s/blog_4b20ae2e0101h84o.html Android Icon Size and Location for Apps DENS ...

  8. rest framework之限流组件

    一.自定义限流 限流组件又叫做频率组件,用于控制客户端可以对API进行的请求频率,比如说1分钟访问3次,如果在1分钟内超过3次就对客户端进行限制. 1.自定义限流 假设现在对一个API访问,在30s内 ...

  9. 并查集(Disjoint Set Union,DSU)

    定义: 并查集是一种用来管理元素分组情况的数据结构. 作用: 查询元素a和元素b是否属于同一组 合并元素a和元素b所在的组 优化方法: 1.路径压缩 2.添加高度属性 拓展延伸: 分组并查集 带权并查 ...

  10. flexbox布局一

    flexbox布局是一种新的css布局,flex是flexible的简写,所以flexbox就可以理解为可伸缩布局.而可伸缩性也是flexbox布局的亮点,至于如何可伸缩,看完下面的介绍大家应该就会有 ...