搭建一个简单的xxljob

数据库表结构:

YyJobInfo:
public class YyJobInfo {
	//定时任务id
	private int id;
	//该定时任务所属的执行器的id
	private int jobGroup;
	//定时任务描述
	private String jobDesc;
	//定时任务添加的时间
	private Date addTime;
	//定时任务的更新时间
	private Date updateTime;
	//负责人
	private String author;
	//报警邮件
	private String alarmEmail;
	//调度类型
	private String scheduleType;
	//一般为调度的cron表达式
	private String scheduleConf;
	//定时任务的失败策略
	private String misfireStrategy;
	//定时任务的路由策略
	private String executorRouteStrategy;
	//JobHandler的名称
	private String executorHandler;
	//执行器参数
	private String executorParam;
	//定时任务阻塞策略
	private String executorBlockStrategy;
	//执行超时时间
	private int executorTimeout;
	//失败重试次数
	private int executorFailRetryCount;
	//定时任务运行类型
	private String glueType;
	//glue的源码
	private String glueSource;
	//glue备注
	private String glueRemark;
	//glue更新时间
	private Date glueUpdatetime;
	//子任务id
	private String childJobId;
	//定时任务触发状态,0为停止,1为运行
	private int triggerStatus;
	//最近一次的触发时间
	private long triggerLastTime;
	//下一次的触发时间
	private long triggerNextTime;
}

项目分层:

核心代码:

com.yy.yyjob.admin.core.thread.JobScheduleHelper

任务调度代码(有些逻辑采用模拟逻辑,后续会逐渐补全):
@Component
public class JobScheduleHelper {

    @Resource
    private YyJobInfoDao yyJobInfoDao;

    // 调度定时任务的线程
    private Thread scheduleThread;

    // 创建当前类的对象
    private static JobScheduleHelper instance = new JobScheduleHelper();

    // 把当前类的对象暴露出去
    public static JobScheduleHelper getInstance(){
        return instance;
    }

    // 启动调度线程工作的方法
    public void start(){
        scheduleThread = new Thread(new Runnable() {
            @Override
            public void run() {
                while (true){
                    // 从数据库中查询所有定时任务信息
                    List<YyJobInfo> yyJobInfoList =  YyJobAdminConfig.getAdminConfig().getYyJobInfoDao().findAll();
                    // 得到当前时间
                    long time = System.currentTimeMillis();
                    // 遍历所有定时任务信息
                    for (YyJobInfo yyJobInfo : yyJobInfoList) {
                        if (time > yyJobInfo.getTriggerNextTime()){
                            // 如果大于就执行定时任务,在这里就选用集合的第一个地址
                            System.out.println("通知address服务器,去执行定时任务");
                            // 计算定时任务下一次的执行时间
                            Date nextTime = null;
                            try {
                                 nextTime = new CronExpression(yyJobInfo.getScheduleConf()).getNextValidTimeAfter(new Date());
                            } catch (ParseException e) {
                                e.printStackTrace();
                            }
                            // 下面就是更新数据库中定时任务的操作
                            YyJobInfo job = new YyJobInfo();
                            job.setTriggerNextTime(nextTime.getTime());
                            System.out.println("保存job信息");
                        }
                    }
                }
            }
        });
        scheduleThread.start();
    }
数据库配置代码:
/**
 * @Description:
 * 这个类可以说是服务端的启动入口,该类实现了Spring的InitializingBean接口,
 * 所以该类中的 afterPropertiesSet方法会在容器中的bean初始化完毕后被回掉。回掉的过程中会创建xxl-job中最重要的块慢线程池
 * 同时也会启动xxl-job中的时间轮
 */
@Component
public class YyJobAdminConfig implements InitializingBean, DisposableBean {
    //当前类的引用,看到这里就应该想到单例模式了
    //xxl-job中所有组件都是用了单例模式,通过public的静态方法把对象暴露出去
    private static YyJobAdminConfig adminConfig = null;

    //获得当前类对象的静态方法
    public static YyJobAdminConfig getAdminConfig() {
        return adminConfig;
    }

    @Override
    public void afterPropertiesSet() throws Exception {
        //为什么这里可以直接赋值呢?还是和spring的bean对象的初始化有关,XxlJobAdminConfig添加了@Component
        //注解,所以会作为bean被反射创建,创建的时候会调用无参构造器
        //而afterPropertiesSet方法是在容器所有的bean初始化完成式才会被回掉,所以这时候XxlJobAdminConfig对象已经
        //创建完成了,直接赋值this就行
        adminConfig = this;
    }

    @Override
    public void destroy() throws Exception {
    }

    @Resource
    private YyJobInfoDao yyJobInfoDao;
    @Resource
    private DataSource dataSource;

    public YyJobInfoDao getYyJobInfoDao() {
        return yyJobInfoDao;
    }

    public DataSource getDataSource() {
        return dataSource;
    }

总结:

目前调度中心单独部署在一台服务器中,两个定时任务程序各自部署在不同的服务器上。调度中心和定时任务程序启动的时候,会先启动调度中心,然后再启动定时任务程序。这样,定时任务程序才能把定时任务的信息和定时任务部署的服务器的ip地址发送给调度中心,然后调度中心把这些信息记录在数据库中。然后,调度中心的调度任务的线程就会开始在一个while循环中不断地扫描数据库,查找数据库能够执行的定时任务,如果有定时任务到了执行时间了,就远程通知执行定时任务的程序执行定时任务,接着在计算定时任务下一次的执行时间,记录时间到数据库中。

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

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

TIM: A Time Interval Machine for Audio-Visual Action Recognition

标题&#xff1a;TIM&#xff1a;一种用于视听动作识别的时间间隔机器 源文链接&#xff1a;openaccess.thecvf.com/content/CVPR2024/papers/Chalk_TIM_A_Time_Interval_Machine_for_Audio-Visual_Action_Recognition_CVPR_2024_paper.pdfhttps://openaccess.thecvf.com/cont…

Redis 持久化策略

Redis 提供了多种持久化机制&#xff0c;用于将数据保存到磁盘中&#xff0c;以防止因服务器重启或故障而导致的数据丢失。主要的持久化策略有两种&#xff1a;RDB (Redis Database) 和 AOF (Append Only File)&#xff0c;即当 Redis 服务器重新启动时&#xff0c;会读取相应的…

SEGGER Embedded Studio IDE移植embOS

SEGGER Embedded Studio IDE移植embOS 一、背景介绍二、任务目标三、技术实现3.1 获得embOS3.2 创建SES工程3.2.1 创建初始Solution和Project3.2.2 制作项目文件结构3.2.3 移植embOS库和有关头文件3.2.3.1 头文件3.2.3.2 库文件3.2.3.3 创建RTOSInit.c源文件3.2.3.4 OS_Error.c…

鸿蒙HarmonyOS NEXT角落里的知识:ArkTS高性能编程实践

概述 本文主要提供应用性能敏感场景下的高性能编程的相关建议&#xff0c;助力开发者开发出高性能的应用。高性能编程实践&#xff0c;是在开发过程中逐步总结出来的一些高性能的写法和建议&#xff0c;在业务功能实现过程中&#xff0c;我们要同步思考并理解高性能写法的原理…

信息学奥赛初赛天天练-31-CSP-J2022基础题-指针、数组、链表、进制转换、深度优先搜索、广度优先搜索、双栈实现队列应用

PDF文档公众号回复关键字:20240621 2022 CSP-J 选择题 单项选择题&#xff08;共15题&#xff0c;每题2分&#xff0c;共计30分&#xff1a;每题有且仅有一个正确选项&#xff09; 3.运行以下代码片段的行为是 ( ) int x 101; int y 201; int * p &x; int * q &y;…

【Java】已解决java.net.ProtocolException异常

文章目录 一、分析问题背景二、可能出错的原因三、错误代码示例四、正确代码示例五、注意事项 已解决java.net.ProtocolException异常 在Java的网络编程中&#xff0c;java.net.ProtocolException异常通常表示在网络通信过程中&#xff0c;客户端或服务器违反了某种协议规则。…

ASP.NET Core 6.0 启动方式

启动方式 Visualstudio 2022启动 IIS Express IIS Express 是一个专为开发人员优化的轻型独立版本的 IIS。 借助 IIS Express,可以轻松地使用最新版本的 IIS 开发和测试网站。 控制台版面 直接在浏览器输入监听的地址,监听的是 http://localhost:5137 脚本启动 dotnet run…

Java中将文件转换为Base64编码的字节码

在Java中&#xff0c;将文件转换为Base64编码的字节码通常涉及以下步骤&#xff1a; 读取文件内容到字节数组。使用java.util.Base64类对字节数组进行编码。 下面是一个简单的Java示例代码&#xff0c;演示如何实现这个过程&#xff1a; import java.io.File; import java.io…

添加右键菜单(以git为例)

1、打开注册表编辑器 打开系统注册表&#xff0c;使用组合键“Win R”输入“regedit”。 依次展开”HKEY_CLASSES_ROOT\Directory\Background\shell”。 2、新建右键菜单项 在[Background]下找到“shell”如果没有则新建项shell&#xff0c;接着在“shell”下右键-新建项名…

Linux 线程的同步与互斥

&#x1f493;博主CSDN主页:麻辣韭菜&#x1f493;   ⏩专栏分类&#xff1a;Linux初窥门径⏪   &#x1f69a;代码仓库:Linux代码练习&#x1f69a;   &#x1f339;关注我&#x1faf5;带你学习更多Linux知识   &#x1f51d; 前言 1.资源共享问题 2.进程线程间的互斥…

谁拥有数字营销平台即拥有企业竞争力!

掌握数字营销平台&#xff0c;就等于掌握企业竞争力&#xff01; 宝子们&#xff0c;咱今天来聊聊这个事儿哈。在现在这个数字化的时代&#xff0c;拥有像蚓链这样的数字营销平台那可太重要啦&#xff01; 想想看&#xff0c;有了它&#xff0c;企业就能更广、更快地去推广…

创新案例|星巴克中国市场创新之路: 2025目标9000家店的挑战与策略

星巴克创始人霍华德舒尔茨&#xff1a;“为迎接中国市场的全面消费复苏&#xff0c;星巴克2025年推进9000家门店计划&#xff0c;将外卖、电商以及家享和外出场景咖啡业务纳入中国新一轮增长计划中。”在面临中国市场同店增长大幅下滑29%背景下&#xff0c;星巴克通过DTC用户体…

Word中删除空白页

① 文字后面出现的空白页 把鼠标放在空白页的位置&#xff0c;按住Ctrl Delete即可。 ② 表格后面的空白页 把鼠标放在空白页左侧&#xff0c;直到出现一个空白的箭头&#xff0c;点击一下选中空白页&#xff0c;然后再Ctrl D&#xff0c;打开字体选项卡&#xff0c;在效果中…

舔狗日记Puls微信小程序源码

源码介绍&#xff1a; 这是一款舔狗日记Puls微信小程序源码&#xff0c;提供每日一舔的功能&#xff0c;让你舔到最后&#xff0c;什么都有&#xff01; 源码通过API获取一些舔狗日记&#xff0c;内置了100多句舔狗日记&#xff0c;让你摆脱上班摸鱼的无聊时光&#xff0c; …

[240621] Anthropic 发布了 Claude 3.5 Sonnet AI 助手 | Socket.IO 拒绝服务漏洞

目录 Anthropic 发布 Claude 3.5 Sonnet AI 助手Scoket.IO 拒绝服务漏洞&#xff08;CVE-2024-38355&#xff09; Anthropic 发布 Claude 3.5 Sonnet AI 助手 Claude 3.5 Sonnet: 更智能、更快速、更安全的 AI 助手 一、 引言 Anthropic 发布了 Claude 3.5 Sonnet&#xff0…

C语言中操作符详解(一)

众所周知&#xff0c;在我们的C语言中有着各式各样的操作符&#xff0c;并且在此之前呢&#xff0c;我们已经认识并运用了许许多多的操作符&#xff0c;都是诸君的老朋友了昂 操作符作为我们使用C语言的一个非常非常非常重要的工具&#xff0c;诸君一定要加以重视&#xff0c;…

DevOps学习回顾01-技能发展路线-岗位能力-体系认知

事为先&#xff0c;人为重–事在人为 参考来源&#xff1a; 极客时间专栏&#xff1a;DevOps实战笔记&#xff0c;作者&#xff1a;石雪峰 课程链接&#xff1a;https://time.geekbang.org/column/intro/235 时代的典型特征 VUCA VUCA 是指易变性&#xff08;Volatility&…

【Android面试八股文】你能说一说自定义View与ViewGroup的区别

文章目录 Android UI 组件:View 和 ViewGroupViewGroup 的职责View 的职责自定义 View 和 ViewGroup 的区别1. 继承的类不同2. 主要功能不同3. 重写方法不同4. 使用场景不同5. 事件分发方面的区别6. UI 绘制方面的区别Android UI 组件:View 和 ViewGroup 在 Android 开发中,…

AI通用大模型不及垂直大模型?各有各的好

​​​​​​​AI时代&#xff0c;通用大模型和垂直大模型&#xff0c;两者孰优孰劣&#xff0c;一直众说纷纭。 通用大模型&#xff0c;聚焦基础层&#xff0c;如ChatGPT、百度文心一言&#xff0c;科大讯飞星火大模型等&#xff0c;都归属通用大模型&#xff0c;它们可以解答…

使用ASP.NET Core封装接口请求参数格式

有些人获取接口请求参数是直接使用数据库实体类来获取的&#xff0c;这种方式虽然写起来很方便&#xff0c;但是会导致swagger接口文档出现很多没用的参数&#xff0c;让人看着不舒服。 比如&#xff0c;新增用户只需要传用户名、密码、邮箱就可以了&#xff0c;但是实体类也包…