ScheduledThreadPoolExecutor定时任务执行线程池分析

news2024/10/6 4:06:05

概述

ScheduledThreadPoolExecutor自然是继承了ThreadPoolExecutor,那么它也就是一个被定义了特定功能的线程池而已,本质上就是一个ThreadPoolExecutor。

代码分析

可以看到其继承了ThreadPoolExecutor,在new ScheduledThreadPoolExecutor实例的时候,调用的是父类的构造函数。

在new的时候其传入了初始核心线程数,最大线程数为Integer.MAX_VALUE,线程空闲存活时间为0,默认的拒绝策略是抛异常给调用线程。

这里传入的队列是DelayedWorkQueue
顾名思义就是按照执行时间的升序来排列,执行时间距离当前时间越近的任务在队列的前面。

图例分析

继承关系
在这里插入图片描述

实例化调用父类构造
在这里插入图片描述

父类构造方法
在这里插入图片描述
默认的线程池拒绝策略是抛异常给调用线程
在这里插入图片描述

传入的队列是DelayedWorkQueue
会自动增长容量,最大是Integer.MAX_VALUE。所以正常情况下,线程池最多就保持corePoolSize数量的活跃线程
在这里插入图片描述

DelayedWorkQueue

顾名思义就是按照执行时间的升序来排列,执行时间距离当前时间越近的任务在队列的前面。
核心数据结构是二叉最小堆的优先队列.其容量会动态增长(增长的时候每次增加50%的容量)。

DelayedWorkQueue是一个基于堆的数据结构,类似于DelayQueuePriorityQueue.在执行定时任务的时候,每个任务的执行时间都不同,所以DelayedWorkQueue的工作就是按照执行时间的升序来排列,执行时间距离当前时间越近的任务在队列的前面(注意:这里的顺序并不是绝对的,堆中的排序只保证了子节点的下次执行时间要比父节点的下次执行时间要大,而叶子节点之间并不一定是顺序的)。

在这里插入图片描述
用数组来表示就是这样的
在这里插入图片描述
在这种结构中,可以发现有如下特性:
假设第一个元素”在数组中的下标为0的话,则父结点和子结点的位置关系如下:

索引为 的左孩子的索引是 (2∗i+1)(2 * i + 1)(2∗i+1)
索引为 的右孩子的索引是 (2∗i+2)(2 * i + 2)(2∗i+2)
索引为 的父结点的索引是 floor((i−1)/2)floor((i-1)/2)floor((i−1)/2)

代码demo

ScheduledThreadPoolExecutor中的
schedule:一次性定时任务
scheduleWithFixedDelay:周期性执行,下次执行时间=上一次任务从执行到结束所需要的时间+给定的间隔时间。

scheduleAtFixedRate:周期性执行,创建一个给定初始延迟的间隔性的任务,之后的每次任务执行时间为 初始延迟 + N * delay(间隔) 。这里的N为首次任务执行之后的第N个任务,N从1开始。比如首次执行任务的时间为12:00 那么下次任务的执行时间是固定的 是12:01 下下次为12:02。与scheduleWithFixedDelay最大的区别就是 ,scheduleAtFixedRate 不受任务执行时间的影响。

获取内容

package com.xxx.xxx;

import com.cloud.common.core.enums.system.UserQueryType;
import com.xxx.xxx.xxx.SysUserService;
import org.apache.commons.collections4.CollectionUtils;
import org.springframework.beans.factory.InitializingBean;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Component;

import javax.annotation.Resource;
import java.util.List;
import java.util.Map;
import java.util.Objects;
import java.util.concurrent.*;

@Component
public class QueryTypeContext implements InitializingBean {


    private static SysUserService sysUserService;

    @Value("${queryType.refresh.threadCount:8}")
    private Integer threadCount;

    public static ScheduledExecutorService executorService;

    private static List<String> qcRoleKeys;

    private static Map<String,QueryTypeRefreshTask> refreshQueryType = new ConcurrentHashMap<>();



    @Resource
    public void setSysUserService(SysUserService sysUserService) {
        QueryTypeContext.sysUserService = sysUserService;
    }


    public static List<String> getQcRoleKeys() {
        if(CollectionUtils.isEmpty(qcRoleKeys)){
            synchronized (QueryTypeContext.class){
                if(CollectionUtils.isEmpty(qcRoleKeys)){
                    qcRoleKeys = getSyncRoleKeysByQueryType(UserQueryType.QC.getCode());
                }else {
                    return qcRoleKeys;
                }
            }
        }
        return qcRoleKeys;
    }

    public static void setQcRoleKeys(List<String> qcRoleKeys) {
        QueryTypeContext.qcRoleKeys = qcRoleKeys;
    }

    private static List<String> getSyncRoleKeysByQueryType(String queryType){
        startRefreshConfig(queryType);
        return sysUserService.getSyncRoleKeysByQueryType(queryType);
    }

    private static void startRefreshConfig(String type){
        QueryTypeRefreshTask queryTypeRefreshTask = refreshQueryType.get(type);
        if(Objects.isNull(queryTypeRefreshTask)){
            synchronized (QueryTypeContext.class){
                queryTypeRefreshTask = refreshQueryType.get(type);
                if(Objects.isNull(queryTypeRefreshTask)){
                    QueryTypeRefreshTask task = new QueryTypeRefreshTask(sysUserService, type);
                    //一次性任务,按照指定时间延时
                    //executorService.schedule(task, 10, TimeUnit.SECONDS);
                    //周期性执行任务,按照指定时间周期性执行
                    executorService.scheduleWithFixedDelay(task, 10, 10,TimeUnit.SECONDS);
                    refreshQueryType.put(type, task);
                }
            }
        }
    }


    @Override
    public void afterPropertiesSet() throws Exception {
        QueryTypeContext.executorService = new ScheduledThreadPoolExecutor(threadCount, new ThreadFactory() {
            @Override
            public Thread newThread(Runnable r) {
                Thread thread = new Thread(r);
                thread.setDaemon(true);
                thread.setName("com.cloud.system#refresh");
                return thread;
            }
        });
    }
}

具体任务

package com.xx.xx;

import com.xx.xx.xx.SysUserService;

public class QueryTypeRefreshTask implements Runnable{

    private SysUserService sysUserService;

    private String type;

    public QueryTypeRefreshTask() {
    }

    public QueryTypeRefreshTask(SysUserService sysUserService, String type){
        this.sysUserService = sysUserService;
        this.type = type;
    }

    @Override
    public void run() {

        QueryTypeContext.setQcRoleKeys(
                sysUserService.getSyncRoleKeysByQueryType(type)
        );

    }
}

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/148512.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

【FPGA】Verilog 编码实现:与非门 | 或非门 | 异或门 | NAND/NOR/XOR 行为验证

写在前面&#xff1a;本章主要内容为了解和确认 NAND/NOR/XOR 门的行为&#xff0c;并使用Verilog实现&#xff0c;生成输入信号后通过模拟&#xff0c;验证每个门的操作&#xff0c;并使用 FPGA 来验证 Verilog 实现的电路的行为。 本章目录&#xff1a; Ⅰ. 前置知识 0x00…

C++ 排序大合集

目录 一、了解排序 1、内部 2、外部 二、排序的稳定性 三、插入排序 1、算法和操作 2、代码 四、选择排序 1、算法和操作 2、代码 五、冒泡排序 1、算法和操作 2、代码 六、堆排序 1、优先队列 2、排序代码 七、归并排序 1、定义 2、基本算法 &#xff08;1&#xff09;、分离 …

宝塔Linux面板安装MySQL数据库,并且开启远程链接

1.宝塔面板【软件商店】->【应用搜索】&#xff0c;搜索MySQL,然后点击安装想要的版本&#xff0c;我这边是安装的5.6版 2. 安装完后重置数据库管理员密码 3.Navicat Premium 15连接数据库 4.外网navicat工具无法连接数据库的处理办法 4.1输入 mysql -u root -p 后回车&a…

零基础入门反序列化漏洞

目录 前提知识 漏洞产生原理 常见的函数 序列化 反序列化 __sleep函数 私有和保护 __wakeup函数 反序列化漏洞举例 构造XSS漏洞 反序列化免杀后门 POP CHAIN(POP链) 前提知识 漏洞产生原理 serialize() 和 unserialize() 在 PHP内部实现上是没有漏洞的&#xf…

Cadence PCB仿真使用Allegro PCB SI配置电路板层叠结构的方法图文教程

⏪《上一篇》   🏡《总目录》   ⏩《下一篇》 目录 1,概述2,配置方法3,总结1,概述 本文详细介绍使用Allegro PCB SI软件配置电路板层叠结构的方法。 2,配置方法 第1步:打开待仿真的PCB文件,并确认软件为Allegro PCB SI 如果,打开软件不是Allegro PCB SI则可这样…

解决No module named tkinter

原因 今天准备使用tutle画个图&#xff0c;导入turtle后运行发现提示没有tkinter这个包&#xff0c;于是尝试pip install tkinter安装&#xff0c;结果当然是失败&#xff1a; 后面一番搜索之后发现tinter是python3自带的包&#xff0c;不能用pip安装&#xff0c;我这里安装的…

JS的六种继承方式

继承 什么是继承&#xff1f; JS里的继承就是子类继承父类的属性和方法 目的可以让子类的实例能够使用父类的属性和方法 抽象的表达就是&#xff1a;一个人有车&#xff0c;有房&#xff0c;那么他的儿子也可以去使用他的车子&#xff0c;住他的房子。 方法一&#xff1a;…

Seata流程源码梳理上篇-TM、RM处理

这一篇我们主要来分析下Seata的AT模式的流程处理。一、流程案例 1、案例源码 ​ 我们本地流程梳理用的是基于spring-cloud框架&#xff0c;注册中心是eurak&#xff0c;服务间调用的是feign&#xff0c;源码下载的是官网的&#xff08;当然你如果对dubbo更熟悉&#xff0c;也…

CSDN博客之星年度评选活动 - 2022

文章目录一、2022年CSDN博客之星评选活动报名二、2022年CSDN博客之星评选活动流程线上评分流程争议&#xff08;官方最后证实公布后会更新&#xff09;三、2022年CSDN博客之星评选规则四、2022年CSDN博客之星评分规则五、2022年CSDN博客之星活动奖品「博客之星」奖品「博客新星…

CInternetSession OpenURL没反应,不能捕获异常

本文迁移自本人网易博客&#xff0c;写于2013年10月22日CString sFileName;CInternetSession iSession;BOOL bRet FALSE;CStdioFile* pFileDown NULL;try{pFileDown iSession.OpenURL(szURL, 1, INTERNET_FLAG_TRANSFER_BINARY|INTERNET_FLAG_DONT_CACHE);}catch(...){CStri…

2023/1/8 Vue学习笔记-4-脚手架及相关属性配置

1 创建脚手架 &#xff08;1&#xff09;CLI就是 command line interface 的缩写。Vue CLI官网&#xff1a;Vue CLI &#xff08;2&#xff09;安装过程&#xff1a; &#xff08;PS&#xff1a; 提前安装过node.js了&#xff0c;没有安装的可以打开这个&#xff1a;Download …

什么是布隆过滤器?——超详细解析【建议收藏】

目录 1、什么是布隆过滤器&#xff1f; 2、实现原理 2.1、回顾哈希函数 2.1.1、哈希函数概念 2.1.2、散列函数的基本特性&#xff1a; 2.2、布隆过滤器数据结构 3、特点 3.1、支持删除吗&#xff1f; 3.2、优点 3.3、缺点 3.4、误判率 4、如何选择哈希函数个数和布…

3 机器学习之聚类

学习笔记自&#xff0c;慕课网 《Python3 入门人工智能》 https://coding.imooc.com/lesson/418.html#mid32716 分类问题 1. 无监督学习 机器学习的一种方法&#xff0c;没有给定事先标记过的训练示例&#xff0c;自动对输入的数据进行分类或分群 优点&#xff1a; 1&#xf…

今年十八,喜欢CTF-杂项

目录 前言 菜狗杯杂项签到 我吐了你随意 损坏的压缩包 misc4 misc5 前言 &#x1f340;作者简介&#xff1a;被吉师散养、喜欢前端、学过后端、练过CTF、玩过DOS、不喜欢java的不知名学生。 &#x1f341;个人主页&#xff1a;被吉师散养的职业混子 &#x1fad2;每日emo&am…

Rad Studio 11.2 安装 QuickBurro 7.21 中间件组件教程

背景 QuickBurro 官方网址&#xff1a;http://www.quickburro.org/ 系统环境&#xff1a;Rad Studio 11.2 安装其他的组件操作和这个一样的&#xff0c;同样可以参考 开始配置 先打开 Rad Studio 11&#xff0c;依次点击 File–Open Project… 然后找到你解压的 qbcn 目录下的…

React 环境搭建以及创建项目工程(二)

创建工程 首先创建一个工程 npx create-react-app weibo cd移动到当前创建的文件下 cd weibo 安装 React 路由 npm install react-router react-router-dom5.2.0 --save 安装 npm install 安依赖包 npm install antd --save npm install axios --save 安装less和less-…

PyCharm安装步骤

以64位的Windows10系统为例&#xff1a; 下载链接&#xff1a;Thank you for downloading PyCharm! 下载并打开安装包 在 Installation Options&#xff08;安装选项&#xff09;页面按下图所示勾选相应内容&#xff1a; 等待电脑自动安装完成 在PyCharm里编写程序 第1步&a…

【python】天平最少砝码设计

题目 有一架天平&#xff0c;砝码的种类和个数要你来设计。给定一个整数n&#xff0c;则待称重的物品的重量可能是 [1,n] 之间的整数&#xff0c;砝码可以放在左盘也可以放在右盘&#xff0c;要能称出所有 [1,n] 重量的物品&#xff0c;请问如何设计砝码的种类和个数&#xff…

Unreal UFUNCTION函数宏标记

BlueprintCallable,使C中的函数在蓝图中能被调用,新建C类CustomActor继承AActor,并分别声明public、protected、private方法:拖拽一个CustomActor到Map中,打开关卡蓝图,可以到无法在蓝图中调出C中的方法:我们为这三个方法添加BlueprintCallable标记:然后在蓝图中调用:可以发现,…

驱动程序开发:多点电容触摸屏

驱动程序开发&#xff1a;多点电容触摸屏一、编写驱动前的知识准备1、CST340触摸屏芯片寄存器2、CST340触摸屏的硬件原理图3、电容触摸屏驱动是由几种linux驱动框架组成的4、linux多点电容触摸的(Multi-touch&#xff0c;简称 MT)协议二、驱动程序的编写1、修改设备树2、驱动程…