任务调度 111

定时任务概述

Java 中开发定时任务主要有三种解决方案:一是使用JDK 自带的 Timer,二是使用 Spring Task,三是使用第三方组件 Quartz

Timer 是 JDK 自带的定时任务工具,其简单易用,但是对于复杂的定时规则无法满足

Spring Task使用起来很简单,除 Spring 相关的包外不需要额外的包,而且支持注解和配置文件两种形式

Quartz 功能强大,但是使用起来相对笨重

一般来说      单体项目架构使用Spring Task      分布式项目框架使用Quartz

JDK实现任务调度

 //创建定时类
        Timer timer = new Timer();
        //创建任务类
        TimerTask task = new TimerTask() {
            @Override
            public void run() {
                System.out.println("定时任务执行了......"+ LocalDateTime.now().format(DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss")));
            }
        };
        //执行定时任务
        timer.schedule(task,new Date(),2000);

Spring-task实现任务调度

搭建springBoot工程,导入依赖

编写启动类,打开任务调度注解

@SpringBootApplication
@EnableScheduling
public class TaskStudyApplication {

    public static void main(String[] args) {
        SpringApplication.run(TaskStudyApplication.class, args);
    }
}

最后编写测试类

@Component
public class SpringTask {
    @Scheduled(cron = "*/1 * * * * *")
    public void task1() throws InterruptedException {
        System.out.println(Thread.currentThread().getName()+":task1--->"+ LocalDateTime.now());
    }
}

Spring-task 分析

编写任务调度,可调度程序加一下执行时间,模拟真实业务

@Scheduled(cron = "*/1 * * * * *")
public void task1() throws InterruptedException {
    System.out.println(Thread.currentThread().getName()+":task1--->"+ LocalDateTime.now());
    Thread.sleep(5000);
}

发现任务调度并不是每秒执行1次,而是6秒执行一次。我们在看执行线程的名字都是一样的,由此可以得出Spring-task执行的任务是基于单线程执行的

所以可得

Spring-task 执行任务按照单线程执,不会因为第一个执行任务时间过长而执行第二个

Spring-task是单线程的处理任务能力有限,不建议处理分布式架构的任务调度。

Cron表达式讲解

Quartz 基本应用

相较于Timer, Quartz增加了很多功能

持久性作业 - 就是保持调度定时的状态;

作业管理 - 对调度作业进行有效的管理;

Quartz 的核心类有以下三部分:

  • 任务 Job : 需要实现的任务类,实现 execute() 方法,执行后完成任务。

  • 触发器 Trigger : 包括 SimpleTriggerCronTrigger

  • 调度器 Scheduler : 任务调度器,负责基于 Trigger触发器,来执行 Job任务

创造工程,导入依赖

创建调度器、jobDetail 实例、trigger 实例、执行  

QuartzTest

 //1.创建任务调度器
        SchedulerFactory factory = new StdSchedulerFactory();
        Scheduler scheduler = factory.getScheduler();

        //2.创建JobDetail实例,并与MyJob类绑定
        JobDetail job = JobBuilder.newJob(MyJob.class)
                //指定任务名,组名
                .withIdentity("job1","group1")
                .build();

        //3.构建Trigger实例,每隔3s执行一次
        Trigger trigger = TriggerBuilder.newTrigger()
                //指定触发器名字,组名
                .withIdentity("trigger1","group1")
                //从现在触发
                .startNow()
                //触发规则3s触发一次
                .withSchedule(SimpleScheduleBuilder.simpleSchedule().withIntervalInSeconds(3).repeatForever())
                .build();

        //4.执行 开启任务调度器
        scheduler.scheduleJob(job,trigger);
        System.out.println(System.currentTimeMillis());
        scheduler.start();

QuartzAPI详解

JobDetail 的作用是绑定 Job,是一个任务实例

jobDetail 为job增添了很多扩展参数

问题  为u、为什么要用JobDetail + Job,不直接使用Job

JobDetail 定义的是任务数据,而真正的执行逻辑是在Job中。

这是因为任务是有可能并发执行,如果Scheduler直接使用Job,就会存在对同一个Job实例并发访问的问题。

JobDetail+Job 方式,Sheduler每次执行,都会根据JobDetail创建一个新的Job实例,这样就可以 规避并发访问 的问题。

SimpleTrigger

比较简单的一类触发器

在指定时间段内,执行一次任务

最基础的 Trigger 不设置循环,设置开始时间。

在指定时间段内,循环执行任务

在执行完一次任务的基础上加上循环间隔。可以指定 永远循环、运行指定次数

Trigger trigger = TriggerBuilder.newTrigger()
                .withIdentity("trigger2","group1")
                .startNow()
                .withSchedule(
                        //使用简单触发器
                        SimpleScheduleBuilder.simpleSchedule().
                        //3s间隔执行
                        withIntervalInSeconds(3).
                        //始终执行//例子比如执行6次   count+1
                        repeatForever())
                        //withRepeatCount(5))

                .build();

CronTrigger

基于日历的任务调度器

 //使用日历触发器
                        CronScheduleBuilder.cronSchedule("0/1 * * * * ? "))

SpringBoot整合Quartz

Quartz 集群执行与单机执行区别

Quartz是一个开源的作业调度框架 Quartz集群和非集群的区别主要体现在 :高可用性   负载均衡   

数据共享。

  1. 高可用性:Quartz集群可以提供高可用性,即使其中一个节点出现故障,其他节点仍然可以继续工作。而非集群模式下,如果应用程序所在的服务器出现故障,任务调度将会停止。

  2. 负载均衡:Quartz集群可以通过将任务分配给不同的节点来实现负载均衡。这意味着任务将在集群的各个节点上分布,从而提高系统整体的性能和吞吐量。非集群模式下,所有的任务将在单个节点上运行,可能会导致性能瓶颈。

  3. 数据共享:Quartz集群可以共享任务调度的数据,包括作业和触发器等。这意味着当一个节点添加或删除任务时,其他节点也能够感知到。非集群模式下,每个节点都有自己独立的任务调度数据,可能导致数据不一致。

大总结

什么是任务调度?

任务调度就是按照特定时间规则执行系统某个固定的业务逻辑。任务调度底层是使用jdk的Timer实现的。单体项目建议使用Spring-task任务调度技术,分布式架构使用quartz任务调度框架。Spring-task是单线程运行旳,Quartz是多线程运行的,且功能更为丰富,更加全面,支持作业管理。

用过什么任务调度技术,他们的区别是什么?

Spring-task是单线程,且功能简单。执行任务只需开启开关@EnableScheduling,在要执行的任务方法上加

@Scheduled(cron = "*/1 * * * * *")注解。它的使用弊端:

  1. 任务A的执行时间会影响任务B的执行间隔,但是任务A和任务B是两个任务,不应该相互影响。

  2. 没有固定组件,持久化等功能,也就没法形成作业系统

Quartz是多线程的高可用的任务调度框架,支持持久化,多线程,集群模式,且有固定组件结构Job、Trigger、scheduler。他的优点一一说明

  1. 有固定组件,有持久化功能,这样就能基于Quartz开发一个任务调度系统,通过UI界面去管理任务调度。

  2. 任务进行持久化之后,重启服务器会加载持久化的任务继续执行。

  3. 任务支持集群模式,如果任务调度模块是一个集群n个节点,那么任务调度不会因为一个节点挂掉而挂掉,且任务在集群之间形成负载均衡。

 

  • 22
    点赞
  • 20
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值