Spring

Java定时任务调度工具详解

2018-10-17  本文已影响72人  小螺丝钉cici

本篇内容:
什么是定时任务调度?
Java定时任务调度工具详解之 Timer篇
Java定时任务调度工具详解之 Quartz篇

定时任务调度:基于给定的时间点,给定的时间间隔或者给定的执行次数自动执行任务。

Java中定时调度工具:Timer 和 Quartz的区别

1.来源:
Timer由JDK自带,不需要引入多余的jar支持。Quartz需要引入jar包。
2.能力:Quartz时间控制更强大,完善。
3.Timer只有一个后台线程执行任务,Quartz拥有后台执行线程池能够使用多个线程执行任务.
能用 Timer 处理的时候,尽量用 Timer 处理。因为 Quartz 需要的资源更多(写法也不一样)。

ps:Quartz功能比Timer更牛逼,能用Timer就别让Quartz登场, 因为出场费很贵的。

Java定时任务调度工具详解之Timer篇

Timer的定义:有且仅有一个后台线程对多个业务线程进行定时定频率的调度
Timer主要构件:Timer定时器 TimerTask定时任务
通过 timer.schedule(myTimerTask, 2000L, 1000L) ,来定时调度

image.png

Timer的定时调度函数

image.png

Schedule 和 ScheduleAtFixedRate 区别:
Schedule,ScheduleAtFixedRate具有同步并发性。
1.schedule不具有并发性。下一次执行时间是相对于上一次任务结束的时间点。因此存在时间延后,不存在并发性。
2.scheduleAtFixedRate同步并发性。下一次执行时间是相对于上一次执行任务的开始时间点。为了赶上进度。因此执行时间一般不会延误,因此存在并发性。

timer的schedule和scheduleAtFixedRate方法一般情况下是没什么区别的,只在某个情      
况出现时会有区别--当前任务没有来得及完成下次任务又交到手上。

定时任务的执行周期是2s一次,但任务执行需要3s。
此时,schedule 会在第一次任务执行之后,也就是3s之后执行任务。
但是,scheduleAtFixedRate会在第一次执行的2s之后,第二次执行定时任务。

我们来举个例子:
暑假到了老师给schedule和scheduleAtFixedRate两个同学布置作业。
老师要求学生暑假每天写2页,30天后完成作业。
这两个学生每天按时完成作业,直到第10天,出了意外,两个学生出去旅游花了5天时间,这5天时间里两个人都没有做作业。任务被拖延了。

这时候两个学生采取的策略就不同了:
schedule重新安排了任务时间,旅游回来的第一天做第11天的任务,第二天做第12天的任务,最后完成任务花了35天。

scheduleAtFixedRate是个守时的学生,她总想按时完成老师的任务,于是在旅游回来的第一天把之前5天欠下的任务以及第16天当天的任务全部完成了,之后还是按照老师的原安排完成作业,最后完成任务花了30天。

import java.text.SimpleDateFormat;
import java.util.Timer;
import java.util.TimerTask;

public class Test01 {
public static void main(String[] args) {
    final Timer timer = new Timer();
    //timer.scheduleAtFixedRate(new TimerTask() {
    timer.schedule(new TimerTask() {//分别注释这行和上面这行试一试效果
        int count = 1;
        @Override
        public void run() {
            count++;
            if (count  == 10) {
                try {
                    Thread.sleep(5000);
                } catch (InterruptedException e) {
                    System.out.println("延迟5s");
                    e.printStackTrace();
                }
            }
            SimpleDateFormat sf = new SimpleDateFormat(
                    "yyyy MM dd hh:mm:ss");
            System.out.println("当前时间:"
                    + sf.format(System.currentTimeMillis()) + "计划时间:"
                    + sf.format(scheduledExecutionTime()));
        }
    }, 1000, 1000);
  }
}

Timer的缺陷:
1.管理并发任务的缺陷:每次有且仅有一个线程去执行定时任务,如存在多任务会导致任务时间过长(串行)
2.当任务抛出异常时的缺陷:当抛出RuntimeException(如果不捕捉异常),会停止所有任务
3.在以下情况禁止使用
对时效性要求较高的多任务并发作业/对复杂的任务的调度

Java定时任务调度工具详解之 Quartz篇

Quartz特点:
1.强大的调度功能
2.灵活的应用方式
3.分布式和集群能力

三个核心:Jobdetail(调度器),Trigger(触发器) ,Scheduler (任务),就能轻松使用Quartz;
JobDetail用来绑定Job,并且在Job执行的时候携带一些执行的信息;
JobDetail和Tigger通过Builder模式创建;
Scheduler通过Factory模式创建;

image.png
public static void main(String[] args) throws SchedulerException, InterruptedException {
    // 打印当前的时间,格式为2017-01-01 00:00:00
    Date date = new Date();
    SimpleDateFormat sf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
    System.out.println("Current Time Is : " + sf.format(date));
    // 创建一个JobDetail实例,将该实例与HelloJob Class绑定
    JobDetail jobDetail = JobBuilder.newJob(HelloJob.class)
            .withIdentity("myJob").build();
    CronTrigger trigger = (CronTrigger) TriggerBuilder
            .newTrigger()
            .withIdentity("myTrigger", "group1")
            .withSchedule(
                    CronScheduleBuilder.cronSchedule("* * * * * ?"))
            .build();
    // 创建Scheduler实例
    SchedulerFactory sfact = new StdSchedulerFactory();
    Scheduler scheduler = sfact.getScheduler();
    scheduler.start();
    System.out.println("scheduled time is :"
            + sf.format(scheduler.scheduleJob(jobDetail, trigger)));
    //scheduler执行两秒后挂起
    Thread.sleep(2000L);        
    //shutdown(true)表示等待所有正在执行的job执行完毕之后,再关闭scheduler
    //shutdown(false)即shutdown()表示直接关闭scheduler
    scheduler.shutdown(false);
    System.out.println("scheduler is shut down? " + scheduler.isShutdown());
}

一.浅谈Job&JobDetail

image.png

JobDetail为Job提供的重要属性

可以通过 jobDetail 的 getKey() 方法来获取相关信息
jobDetail.getKey().getName();    // 获取名称
jobDetail.getKey().getGroup();    // 获取组名称
jobDetail.getJobClass.getName()    // 获取Job class 的名称
jobDataMap //用来存储特定Job实例的状态信息。

二.JobExecutionContext & JobDataMap

JobExecutionContext
概念:Job能通过JobExecutionContext访问Quartz运行环境以及Job的明细数据,当Scheduler调用Job时能将数据传递给execute()方法

JobDataMap
概念:是一个JDK中Map接口实例,在任务调度时存在于JobExecutionContext中,可将参数对象传递给在运行的Job实例;而且,它自身有方便的方法可存取基本数据类型
获取方式:从JobDataMap中直接获取、在Job实现类中添加setter方法对应JobDataMap的键值

未完待续~~~

https://www.imooc.com/video/15144

上一篇下一篇

猜你喜欢

热点阅读