Java定时器Quartz和Timer

Java定时器之Quartz

简介

  • 官方说明
    Quartz is a richly featured, open source job scheduling library that can be integrated within virtually any Java application - from the smallest stand-alone application to the largest e-commerce system. Quartz can be used to create simple or complex schedules for executing tens, hundreds, or even tens-of-thousands of jobs; jobs whose tasks are defined as standard Java components that may execute virtually anything you may program them to do. The Quartz Scheduler includes many enterprise-class features, such as support for JTA transactions and clustering.
    Quartz是一个功能丰富的开源作业调度库,它可以集成在几乎任何Java应用程序中——从最小的独立应用程序到最大的电子商务系统。Quartz可以用来创建简单或复杂的调度,用于执行数十、数百甚至数万个作业;任务被定义为标准的Java组件,实际上可以执行任何可以编程的任务。Quartz调度器包含许多企业级功能,例如对JTA事务和集群的支持。

  • 官网参考地址

调度操作demo

  • 引入Quartz的jar包
    <dependency>
            <groupId>org.quartz-scheduler</groupId>
            <artifactId>quartz</artifactId>
            <version>2.3.0</version>
        </dependency>
  • 创建相关测试类
/**
 * @program: java_demo
 * @description:
 * @author: Mr.Walloce
 * @create: 2019/07/30 18:10
 **/
public class QuartzTest {

    /**
      * @Description 测试job
      * @Author Mr.Walloce
      * @Date 2019/7/30 18:17
      */
    public static class QuartzTestJob implements Job {

        /**
          * @Description TODO
          * @param jobExecutionContext JobExecutionContext中包含了Quartz运行时的环境以及Job本身的详细数据信息。
          * @Return void
          * @Author Mr.Walloce
          * @Date 2019/7/29 19:17
          */
        public void execute(JobExecutionContext jobExecutionContext) throws JobExecutionException {
            System.out.println("Quartz 测试任务被执行中...");
        }
    }

    /**
      * @Description 调度器(Simple Triggers)
      * @param
      * @Return void
      * @Author Mr.Walloce
      * @Date 2019/7/30 18:19
      */
    public static void mySchedule() {
        try {
            //创建scheduler(调度器)实例
            Scheduler scheduler = StdSchedulerFactory.getDefaultScheduler();

            //创建JobDetail实例,创建要执行的job
            JobDetail jobDetail = JobBuilder.newJob(QuartzTestJob.class)
                    .withIdentity("job1", "group1").build();

            //构建Trigger(触发器)实例,每隔5s执行一次
            Trigger trigger = TriggerBuilder.newTrigger()
                    .withIdentity("trigger1", "group1")
                    //立即生效
                    .startNow()
                    .withSchedule(SimpleScheduleBuilder.simpleSchedule()
                            //每隔5s执行一次
                            .withIntervalInSeconds(5)
                            //一直执行
                            .repeatForever())
                    .build();

            //调度执行任务
            scheduler.scheduleJob(jobDetail, trigger);
            //启动
            scheduler.start();

            //睡眠
            //Thread.sleep(6000);

            //停止
            //scheduler.shutdown();
        } catch (SchedulerException e) {
            e.printStackTrace();
        }
    }

    /**
      * @Description 调度器(Cron Triggers)
      * @param
      * @Return void
      * @Author Mr.Walloce
      * @Date 2019/7/29 18:59
      */
    public static void myCronSchedule() {
        try {
            //创建调度器实例scheduler
            Scheduler scheduler = StdSchedulerFactory.getDefaultScheduler();

            JobDetail job = JobBuilder.newJob(QuartzTestJob.class)
                    .withIdentity("job1", "group1")
                    .build();

            CronTrigger trigger = TriggerBuilder.newTrigger()
                    .withIdentity("trigger1", "group1")
                    //20秒执行一次
                    .withSchedule(CronScheduleBuilder.cronSchedule("0/20 * * * * ?"))
                    .build();

            scheduler.scheduleJob(job, trigger);
        } catch (SchedulerException e) {
            e.printStackTrace();
        }
    }

    public static void main(String[] args) {
        new QuartzTest().mySchedule();
    }
}

**
以上两种触发器的形式调度任务,其中Cron Triggers需要使用到cron表达式
**

  • Quartzs结构说明
    • Job: 是一个接口,只定义一个方法execute(JobExecutionContext context),在实现接口的execute方法中编写所需要定时执行的Job(任务), JobExecutionContext类提供了调度应用的一些信息。
    • JobDetail: Quartz每次调度Job时, 都重新创建一个Job实例, 所以它不直接接受一个Job的实例,相反它接收一个Job实现类。
    • Trigger:是一个类,描述触发Job执行的时间触发规则。主要有SimpleTrigger和CronTrigger这两个子类。
    • Scheduler:代表一个Quartz的独立运行容器, Trigger和JobDetail可以注册到Scheduler中,拥有各自的组及名称,组及名称必须唯一(但可以和Trigger的组和名称相同,因为它们是不同类型的)。Scheduler定义了多个接口方法, 允许外部通过组及名称访问和控制容器中Trigger和JobDetail。

Java定时器之Timer

简介

Timer对象是在Java编程中常用到的定时计划任务功能,它在内部使用多线程的方式进行处理,所以它和多线程技术还是有非常大的关联的。在JDK中Timer类主要负责计划任务的功能,也就是在指定的时间开始执行某一个任务,但封装任务的类却是TimerTask类。
TimerTask是实现接口Runnable的一个抽象类,即任务调度时是启动一个新的线程来执行的。
    public abstract class TimerTask implements Runnable

任务调度源码解析

  1. schedule(TimerTask task, Date time)
     /**
     * Schedules the specified task for execution at the specified time.  If
     * the time is in the past, the task is scheduled for immediate execution.
     *
     * @param task task to be scheduled.
     * @param time time at which task is to be executed.
     * @throws IllegalArgumentException if <tt>time.getTime()</tt> is negative.
     * @throws IllegalStateException if task was already scheduled or
     *         cancelled, timer was cancelled, or timer thread terminated.
     * @throws NullPointerException if {@code task} or {@code time} is null
     */
    public void schedule(TimerTask task, Date time) {
        sched(task, time.getTime(), 0);
    }

**
以上又参数说明可以看出该方法是指在指定的时间开始调度指定的任务
task:被调度执行的任务
time:任务开始调度执行的时间
该方法任务调度,只调度执行一次
**

  1. schedule(TimerTask task, long delay, long period)
    /**
     * Schedules the specified task for repeated <i>fixed-delay execution</i>,
     * beginning after the specified delay.  Subsequent executions take place
     * at approximately regular intervals separated by the specified period.
     *
     * <p>In fixed-delay execution, each execution is scheduled relative to
     * the actual execution time of the previous execution.  If an execution
     * is delayed for any reason (such as garbage collection or other
     * background activity), subsequent executions will be delayed as well.
     * In the long run, the frequency of execution will generally be slightly
     * lower than the reciprocal of the specified period (assuming the system
     * clock underlying <tt>Object.wait(long)</tt> is accurate).
     *
     * <p>Fixed-delay execution is appropriate for recurring activities
     * that require "smoothness."  In other words, it is appropriate for
     * activities where it is more important to keep the frequency accurate
     * in the short run than in the long run.  This includes most animation
     * tasks, such as blinking a cursor at regular intervals.  It also includes
     * tasks wherein regular activity is performed in response to human
     * input, such as automatically repeating a character as long as a key
     * is held down.
     *
     * @param task   task to be scheduled.
     * @param delay  delay in milliseconds before task is to be executed.
     * @param period time in milliseconds between successive task executions.
     * @throws IllegalArgumentException if {@code delay < 0}, or
     *         {@code delay + System.currentTimeMillis() < 0}, or
     *         {@code period <= 0}
     * @throws IllegalStateException if task was already scheduled or
     *         cancelled, timer was cancelled, or timer thread terminated.
     * @throws NullPointerException if {@code task} is null
     */
    public void schedule(TimerTask task, long delay, long period) {
        if (delay < 0)
            throw new IllegalArgumentException("Negative delay.");
        if (period <= 0)
            throw new IllegalArgumentException("Non-positive period.");
        sched(task, System.currentTimeMillis()+delay, -period);
    }

**
设定延迟调度任务及连续执行的时长
delay:延迟调度的时长(毫秒)
period:连续执行的时长(毫秒,任务执行时间间隔)
调度任务执行多次
**

  1. schedule(TimerTask task, long delay)
    /**
     * Schedules the specified task for execution after the specified delay.
     *
     * @param task  task to be scheduled.
     * @param delay delay in milliseconds before task is to be executed.
     * @throws IllegalArgumentException if <tt>delay</tt> is negative, or
     *         <tt>delay + System.currentTimeMillis()</tt> is negative.
     * @throws IllegalStateException if task was already scheduled or
     *         cancelled, timer was cancelled, or timer thread terminated.
     * @throws NullPointerException if {@code task} is null
     */
    public void schedule(TimerTask task, long delay) {
        if (delay < 0)
            throw new IllegalArgumentException("Negative delay.");
        sched(task, System.currentTimeMillis()+delay, 0);
    }

**
延迟执行任务调度
delay:延迟调度的时长(毫秒)
任务调度只执行一次
**

  1. schedule(TimerTask task, Date firstTime, long period)
    /**
     * Schedules the specified task for repeated <i>fixed-delay execution</i>,
     * beginning at the specified time. Subsequent executions take place at
     * approximately regular intervals, separated by the specified period.
     *
     * <p>In fixed-delay execution, each execution is scheduled relative to
     * the actual execution time of the previous execution.  If an execution
     * is delayed for any reason (such as garbage collection or other
     * background activity), subsequent executions will be delayed as well.
     * In the long run, the frequency of execution will generally be slightly
     * lower than the reciprocal of the specified period (assuming the system
     * clock underlying <tt>Object.wait(long)</tt> is accurate).  As a
     * consequence of the above, if the scheduled first time is in the past,
     * it is scheduled for immediate execution.
     *
     * <p>Fixed-delay execution is appropriate for recurring activities
     * that require "smoothness."  In other words, it is appropriate for
     * activities where it is more important to keep the frequency accurate
     * in the short run than in the long run.  This includes most animation
     * tasks, such as blinking a cursor at regular intervals.  It also includes
     * tasks wherein regular activity is performed in response to human
     * input, such as automatically repeating a character as long as a key
     * is held down.
     *
     * @param task   task to be scheduled.
     * @param firstTime First time at which task is to be executed.
     * @param period time in milliseconds between successive task executions.
     * @throws IllegalArgumentException if {@code firstTime.getTime() < 0}, or
     *         {@code period <= 0}
     * @throws IllegalStateException if task was already scheduled or
     *         cancelled, timer was cancelled, or timer thread terminated.
     * @throws NullPointerException if {@code task} or {@code firstTime} is null
     */
    public void schedule(TimerTask task, Date firstTime, long period) {
        if (period <= 0)
            throw new IllegalArgumentException("Non-positive period.");
        sched(task, firstTime.getTime(), -period);
    }

**
首次调度任务的时间及调度时长
firstTime:首次执行调度的时间
period:连续执行的时长(毫秒,任务执行时间间隔)
设定首次执行的时间后,调度多次执行任务
**


任务调度实例

 package com.timer;

import java.util.Date;
import java.util.Timer;
import java.util.TimerTask;

/**
 * @program: java_demo
 * @description: Java中Timer定时器测试
 * @author: Mr.Walloce
 * @create: 2019/07/29 22:36
 **/
public class TimerTest {

    public static class MyTimer extends TimerTask {

        /**
         * The action to be performed by this timer task.
         */
        public void run() {
            //任务执行的逻辑代码块
            System.out.println("任务被调度执行...");
        }
    }

    public static void main(String[] args) {
        Timer t = new Timer();
        MyTimer mt = new MyTimer();
        //立即执行
        //t.schedule(mt, new Date());

        //5s后执行
        //t.schedule(mt, 5000);

        //5s 后执行,每2s执行一次
        //t.schedule(mt, 5000, 2000);

        //每2s执行一次
        t.schedule(mt, new Date(), 2000);
    }
}


Quartz和Timer对比

  • Quartz

    • 非常灵活,可以使用多种形式的定时方式
    • 非常轻量级,而且只需要很少的设置/配置
    • 是容错的,在系统重启后记住以前的记录
    • 可以参与事务
  • Timer

    • 定时器没有持久性机制
    • 创建方便简单,不用另外引入jar包

**
以上为Quartz和Timer两种定时器的简单用法和比较,如有不足或错误,希望补充或指正!
**

初心回归,时光已逝!
原文地址:https://www.cnblogs.com/yin1361866686/p/11267011.html