elastic-job入门(一)

一、概述

本篇文章有很多东西都用到了这位博主的内容:我只是在其基础上加了些自己的理解:https://blog.csdn.net/qq_31278903/article/details/121550273

1.1 什么是任务调度

任务调度:系统为了自动完成特定任务,在约定的特定时刻去执行任务的过程
基础实现方法
1)多线程方式实现:
那么这个就比较简单,让一个线程每睡1s就去执行一次。但是缺点是很难实现在特定时间去做某件事

 public static void main(String[] args) {
        //任务执行间隔时间
        final long timeInterval = 1000;
        Runnable runnable = () -> {
            while (true){
                System.out.println(LocalDateTime.now()+"这是多线程实现任务调度,我将每隔1s执行一次");
                try {
                    Thread.sleep(timeInterval);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
            }
        };
        Thread thread = new Thread(runnable);
        thread.start();
    }

执行后:
在这里插入图片描述

2)JDK提供:Timer方式实现
1个Timer对应1个线程,实际上是多线程去执行。

 public static void main(String[] args) {
        //一个timer就是一个线程
        Timer timer1 = new Timer();
        Timer timer2 = new Timer();
        timer1.schedule(new TimerTask() {
            @Override
            public void run() {
                System.out.println(LocalDateTime.now()+"timer1方式实现任务调度!");

            }
        },1000,2000);//1秒后开始任务调度,每2秒执行一次
         timer2.schedule(new TimerTask() {
            @Override
            public void run() {
                System.out.println(LocalDateTime.now()+"timer2方式实现任务调度!");

            }
        },1000,3000);//1秒后开始任务调度,每3秒执行一次

    }

执行后结果如下:
在这里插入图片描述

3)ScheduledExecutor方式实现:
ScheduledExecutorService为任务调度线程池,可以支持多个线程并行执行任务调度。参数为线程数,如果线程数为1效果和timer一样。
先来看下schedule()方法:延迟一定时间后执行任务
参数一,lambada表达式–要执行的任务
参数二:任务要延迟的时间
参数三:时间单元

public static void main(String[] args) {
        ScheduledExecutorService pool = Executors.newScheduledThreadPool(2);
        // 添加两个任务,希望它们都在 1s 后执行

        pool.schedule(() -> {
            System.out.println("任务1,执行时间:" + LocalDateTime.now());
            try {
                Thread.sleep(2000);
            } catch (InterruptedException ignored) {
            }
        }, 1000, TimeUnit.MILLISECONDS);

        pool.schedule(() -> {
            System.out.println("任务2,执行时间:" + LocalDateTime.now());
        }, 1000, TimeUnit.MILLISECONDS);
    }

输出:
在这里插入图片描述
我们也可以按照像之前指定频率周期性的执行任务
②scheduleAtFixedRate():按指定频率周期执行某个任务
参数一:command:执行线程
参数二:initialDelay:初始化延时
参数三:period:前一次执行结束到下一次执行开始的间隔时间(间隔执行延迟时间)
参数四:unit:计时单位
测试:

public static void main(String[] args) {
    ScheduledExecutorService pool = Executors.newScheduledThreadPool(1);
    log.debug("start...");
    pool.scheduleAtFixedRate(()->{
        log.debug("running...");
    },1,1,TimeUnit.SECONDS);
}

那么我们在这里并不是专门讲解多线程或者线程池,我们主要是想让大家回顾下多线程也可以实现任务调度,每隔一段时间执行特定任务同样也是任务调度的一种。但是他们自己本身却无法实现或者很难实现在特定时间执行特定任务,比方周四晚上八点执行xxx。
那么后面jdk给我们提供了Quartz
4)Quartz 是一个功能强大的任务调度框架,它可以满足更多更复杂的调度需求,Quartz 设计的核心类包括Scheduler, Job 以及Trigger。其中,Job 负责定义需要执行的任务,Trigger 负责设置调度策略,Scheduler 将二者组装在一起,并触发任务开始执行。Quartz支持简单的按时间间隔调度、还支持按日历调度方式,通过CronTrigger表达式(包括:秒、分、时、日、月、周、年)进行任务调度。
要使用Quartz,我们首先需要导入依赖:

<dependency>
    <groupId>org.quartz-scheduler</groupId>
    <artifactId>quartz</artifactId>
    <version>2.3.2</version>
</dependency>

然后写一个任务类实现job接口并重写execute()方法

public class MyTask implements Job {
    @Override
    public void execute(JobExecutionContext jobExecutionContext) {
        System.out.println("这里通过Quartz执行任务");
    }
}

接着测试:

 public static void main(String[] args) throws SchedulerException {
        //第三方Quartz方式实现
        //1.创建一个Scheduler
        StdSchedulerFactory schedulerFactory = new StdSchedulerFactory();
        Scheduler scheduler = schedulerFactory.getScheduler();
        //2.创建jobDetail
        JobBuilder jobBuilder = JobBuilder.newJob(MyTask.class);
        JobDetail jobDetail = jobBuilder.withIdentity("jobName","jobGroupName").build();
        //3.创建触发的CronTrigger 支持按日历调度
        CronTrigger trigger = TriggerBuilder.newTrigger()
                .withIdentity("triggerName", "tiggerGroupName")
                .startNow()
                .withSchedule(CronScheduleBuilder.cronSchedule("0/2 * * * * ?"))
                .build();

        scheduler.scheduleJob(jobDetail,trigger);
        scheduler.start();
    }

1.2、Cron表达式

cron表达式共有 7 个字段,包括Seconds, Minutes, Hours, Day of mouth, Mouth, Day of week, Year,其中 Year 是可选的。

且Day of mouth和Day of week是有冲突的,因为几号是礼拜几这个并不能确定。我们一般通过特殊符号只用其一
在这里插入图片描述
在这里插入图片描述
* :匹配该字段允许的任意值,如果该字符在秒的位置处,表示每秒都会触发事件

- :表示范围,如果在分钟的位置处使用 5-20,即从第 5 分钟到第 20 分钟每分钟触发一次

/ :表示触发的起始时间和间隔时间,如果在分钟位置使用 5/20 ,即从第 5 分钟开始每隔 20 分钟触发一次

, :表示列出枚举值,如果在分钟位置使用 5, 20 ,即在第 5 和第 20 分钟各触发一次

? :只能用在 Day of mouth 和 Day of week 字段中,表示忽略任意值,因为这两个字段值可能会发生冲突,当其中一个值被指定后,需要忽略另一个来避免冲突。

L (last) :表示最后,在 Day of mouth 字段中表示”这个月最后一天”,在 Day of week 字段如果配合数字使用 ,如5L,表示”该月的最后一个星期四”

W (weekday) :工作日,表示最接近指定天的工作日(周一到周五),比如 15W,指最近接本月第15天的工作日,如果那天是周六,则在那周五即前一天触发事件,如果那天是周日,则在下周周一触发事件,如果那天是在周一到周五的范围内,则在当天触发。

# :只能用在 Day of week 字段中,表示该月的第几个周几,如 6#3 表示第3个周五(3 表示第 3 个,6 表示周五),如果指定日期不存在,事件不会触发。
在这里插入图片描述

二、分布式任务调度

2.1、什么是分布式任务调度

什么是分布式
当前软件的架构正在逐步转变为分布式架构,将单体结构分为若干服务,服务之间通过网络交互来完成用户的业务处理,如下图,电商系统为分布式架构,由订单服务、商品服务、用户服务等组成:
在这里插入图片描述
什么是分布式调度
通常任务调度的程序是集成在应用中的,比如:优惠卷服务中包括了定时发放优惠卷的的调度程序,结算服务中包括了定期生成报表的任务调度程序,由于采用分布式架构,一个服务往往会部署多个冗余实例来运行我们的业务,在这种分布式系统环境下运行任务调度,我们称之为分布式任务调度,如下图:
在这里插入图片描述
分布式调度要实现的目标:
1.并行的任务调度,多线程能实现我们当然也要能实现。
2.高可用,比如说一个服务实例崩了另一个实例可以接着执行任务
3.弹性扩容
4.任务管理与监测
5.避免任务重复执行,比方说我的优惠卷我总不能重复发送对吧,我们可以通过以下方式解决这个问题:

  • 分布式锁
  • Zookeeper选举机制
    那么市面上有很多成熟的并且实现了以上目标的产品,这里就来到了我们的主角-elastic-job
    我们将在下一篇重点讲解elastic-job的使用.
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

雨~旋律

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值