zoukankan      html  css  js  c++  java
  • Java 定时调度Timer&Quartz

    目录

    一、Java定时任务介绍

    二、Timer

      1、Timer与TimerTask

      2、schedule

      3、scheduleAtFixRate

    三、Quartz

    一、Java定时任务介绍

      在Java中,用得比较多的有两种,一个是Timer,一个是Quartz;

      其中Timer是这是jdk自带的类库,一般用来实现简单的定时调度,由一个后台线程进行任务的调度,所以对于并发调度不友好;

      Quartz不是jdk自带的,但是他的功能更加强大,一般用于比较复杂的定时调度,可以解决Timer的并发调度问题;

    二、Timer

    2.1、Timer与TimerTask

      Timer是在jdk自带的工具类,Timer为与java.util包下,可以将其理解为一个“定时器”;

      当定时器到点后,执行的任务是TimerTask,称为“任务”;

      下面就是一个TimerTask示例,注意需要重写TimerTask的run方法,类似于Runnable接口的run方法。

    package cn.ganlixin.task;
    
    import java.text.SimpleDateFormat;
    import java.util.Date;
    import java.util.TimerTask;
    
    public class MyTask extends TimerTask {
        @Override
        public void run() {
            SimpleDateFormat dateFormat = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
            System.out.println(dateFormat.format(new Date()));
        }
    }
    

        

      下面是一个简单的定时执行任务的示例:

    package cn.ganlixin.timer;
    
    import cn.ganlixin.task.MyTask;
    import org.junit.Test;
    
    import java.text.ParseException;
    import java.util.Timer;
    
    public class TestTimer {
    
        @Test
        public void testTimerDemo() throws InterruptedException {
            // 创建一个定时器
            Timer timer = new Timer();
    
            // 5秒之后执行任务,只执行一次,执行MyTask的run方法
            // schedule(TimerTask task, long delay)
            timer.schedule(new MyTask(), 5 * 1000L);
    
            // 让当前线程阻塞,等待上面的任务执行
            Thread.sleep(10000);
        }
    }

      Timer有几个可以设置任务执行的方法:

    // 在deley毫秒毫秒后,开始执行task,只执行一次
    void schedule(TimerTask task, long delay)
    
    // 在deley毫秒毫秒后,开始执行task,之后每隔period毫秒执行一次task
    void schedule(TimerTask task, long delay, long period)
    
    // 在date时刻,开始执行task,只执行一次
    void schedule(TimerTask task, Date date)
    
    // 在date时刻,开始执行task,之后每隔period毫秒执行一次task
    void schedule(TimerTask task, Date firstTime, long period)
    
    // 和schedule(TimerTask task, long delay, long period)一样,但是以固定速率执行
    scheduleAtFixedRate(TimerTask task, long delay, long period)
    
    // 和schedule(TimerTask task, Date firstTime, long period)一样,但是以固定速率执行
    scheduleAtFixedRate(TimerTask task, Date firstTime, long period)

      schedule和scheduleAtFixRate有一些区别。

    2.2、schedule

      1、当首次计划执行时间早于当前时间,比如要求在1980年1月1日凌晨执行某个任务

      对于这种情况,启动定时任务后,会立即执行任务。下面是例子:

    package cn.ganlixin.timer;
    
    import org.junit.Test;
    
    import java.text.ParseException;
    import java.text.SimpleDateFormat;
    import java.util.Date;
    import java.util.Timer;
    import java.util.TimerTask;
    
    public class TestTimer {
    
        @Test
        public void testStartBefore() throws InterruptedException, ParseException {
            Timer timer = new Timer();
            SimpleDateFormat dateFormat = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
            System.out.println("当前时间:" + dateFormat.format(new Date()));
    
            Date date = dateFormat.parse("2019-01-01 01:00:00"); // 开始时间为过去
            timer.schedule(new TimerTask() {
                @Override
                public void run() {
                    SimpleDateFormat dateFormat = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
    
                    Date scheduledExecuteTime = new Date(scheduledExecutionTime());
                    System.out.println("预计执行任务时间:" + dateFormat.format(scheduledExecuteTime));
    
                    System.out.println("开始任务:" + dateFormat.format(new Date()));
                    try {
                        Thread.sleep(10000);
                    } catch (InterruptedException e) {
                        e.printStackTrace();
                    }
                    System.out.println("完成任务:" + dateFormat.format(new Date()));
                }
            }, date);
    
            // 让当前线程阻塞,等待上面的任务执行
            Thread.sleep(100000);
        }
    }
    

      运行输出:

    当前时间:2019-03-07 07:56:47
    预计执行任务时间:2019-01-01 01:00:00
    开始任务:2019-03-07 07:56:47
    完成任务:2019-03-07 07:56:57
    

      

      2、首次执行时间在当前时间之后,但是执行时间超过了period(周期)

      比如,有一个任务在4秒后启动,每3秒执行1次,任务每次执行要10秒,此时,因为执行任务所需时间超过了周期时间,所以一次任务执行完后,立即执行下一次任务;

    package cn.ganlixin.timer;
    
    import org.junit.Test;
    
    import java.text.ParseException;
    import java.text.SimpleDateFormat;
    import java.util.Date;
    import java.util.Timer;
    import java.util.TimerTask;
    
    public class TestTimer {
    
        @Test
        public void testTimerDemo() throws InterruptedException, ParseException {
            // 创建一个定时器
            Timer timer = new Timer();
            SimpleDateFormat dateFormat = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
            System.out.println("当前时间:" + dateFormat.format(new Date()));
    
            timer.schedule(new TimerTask() {
                @Override
                public void run() {
                    SimpleDateFormat dateFormat = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
    
                    Date scheduledExecuteTime = new Date(scheduledExecutionTime());
                    System.out.println("预计执行任务时间:" + dateFormat.format(scheduledExecuteTime));
    
                    System.out.println("开始任务:" + dateFormat.format(new Date()));
                    try {
                        Thread.sleep(10000); // 休眠10秒,模拟任务执行耗时
                    } catch (InterruptedException e) {
                        e.printStackTrace();
                    }
                    System.out.println("完成任务:" + dateFormat.format(new Date()));
                    System.out.println("-----------------------------------------");
                }
            }, 4 * 1000L, 3 * 1000L);
    
            // 让当前线程阻塞,等待上面的任务执行
            Thread.sleep(100000);
        }
    }
    

      运行结果:

    当前时间:2019-03-07 08:14:40
    预计执行任务时间:2019-03-07 08:14:44
    开始任务:2019-03-07 08:14:44
    完成任务:2019-03-07 08:14:54
    -----------------------------------------
    预计执行任务时间:2019-03-07 08:14:54
    开始任务:2019-03-07 08:14:54
    完成任务:2019-03-07 08:15:04
    -----------------------------------------
    预计执行任务时间:2019-03-07 08:15:04
    开始任务:2019-03-07 08:15:04
    完成任务:2019-03-07 08:15:14
    -----------------------------------------
    预计执行任务时间:2019-03-07 08:15:14
    开始任务:2019-03-07 08:15:14
    .........
    

      

    2.3、scheduleAtFixRate

      1、当首次计划执行时间早于当前时间,那么scheduleAtFixRate会将错过的这段时间中,本应该执行的任务“补”回来。

    package cn.ganlixin.timer;
    
    import org.junit.Test;
    
    import java.text.ParseException;
    import java.text.SimpleDateFormat;
    import java.util.Date;
    import java.util.Timer;
    import java.util.TimerTask;
    
    public class TestTimer {
    
        @Test
        public void testTimerDemo() throws InterruptedException, ParseException {
            // 创建一个定时器
            Timer timer = new Timer();
            SimpleDateFormat dateFormat = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
            System.out.println("当前时间:" + dateFormat.format(new Date()));
    
            Date date = dateFormat.parse("2019-01-01 01:00:00"); // 开始时间为过去
            timer.scheduleAtFixedRate(new TimerTask() {
                @Override
                public void run() {
                    SimpleDateFormat dateFormat = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
    
                    Date scheduledExecuteTime = new Date(scheduledExecutionTime());
                    System.out.println("预计执行任务时间:" + dateFormat.format(scheduledExecuteTime));
    
                    System.out.println("开始任务:" + dateFormat.format(new Date()));
                    try {
                        Thread.sleep(10000); // 休眠10秒,模拟任务执行耗时
                    } catch (InterruptedException e) {
                        e.printStackTrace();
                    }
                    System.out.println("完成任务:" + dateFormat.format(new Date()));
                    System.out.println("-----------------------------------------");
                }
            }, date, 3 * 1000L);
    
            // 让当前线程阻塞,等待上面的任务执行
            Thread.sleep(100000);
        }
    }
    

      

      2、首次执行时间在当前时间之后,但是执行时间超过了period(周期),此时会将错过的任务补回来

    package cn.ganlixin.timer;
    
    import org.junit.Test;
    
    import java.text.ParseException;
    import java.text.SimpleDateFormat;
    import java.util.Date;
    import java.util.Timer;
    import java.util.TimerTask;
    
    public class TestTimer {
    
        @Test
        public void testTimerDemo() throws InterruptedException, ParseException {
            // 创建一个定时器
            Timer timer = new Timer();
            SimpleDateFormat dateFormat = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
            System.out.println("当前时间:" + dateFormat.format(new Date()));
    
            timer.scheduleAtFixedRate(new TimerTask() {
                @Override
                public void run() {
                    SimpleDateFormat dateFormat = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
    
                    Date scheduledExecuteTime = new Date(scheduledExecutionTime());
                    System.out.println("预计执行任务时间:" + dateFormat.format(scheduledExecuteTime));
    
                    System.out.println("开始任务:" + dateFormat.format(new Date()));
                    try {
                        Thread.sleep(10000); // 休眠10秒,模拟任务执行耗时
                    } catch (InterruptedException e) {
                        e.printStackTrace();
                    }
                    System.out.println("完成任务:" + dateFormat.format(new Date()));
                    System.out.println("-----------------------------------------");
                }
            }, 4 * 1000L, 3 * 1000L);
    
            // 让当前线程阻塞,等待上面的任务执行
            Thread.sleep(100000);
        }
    }
    

      运行输出

    当前时间:2019-03-07 08:26:53
    预计执行任务时间:2019-03-07 08:26:57
    开始任务:2019-03-07 08:26:57
    完成任务:2019-03-07 08:27:07
    -----------------------------------------
    预计执行任务时间:2019-03-07 08:27:00
    开始任务:2019-03-07 08:27:07
    完成任务:2019-03-07 08:27:17
    -----------------------------------------
    预计执行任务时间:2019-03-07 08:27:03
    开始任务:2019-03-07 08:27:17
    完成任务:2019-03-07 08:27:27
    -----------------------------------------
    预计执行任务时间:2019-03-07 08:27:06
    开始任务:2019-03-07 08:27:27
    完成任务:2019-03-07 08:27:37
    

      

    三、Quartz

  • 相关阅读:
    基于网络服务器端的网口测试-软件
    JAVA中操作符的优先级
    逻辑操作符、位操作符号的忽略点
    Java配置环境变量、方法和原因
    Java中常用的字符编码-解析
    SVM
    C#与matlab混合编程
    Python 3 and MySQL
    PyMySQL Evaluation
    PYTHON3连接MYSQL数据库
  • 原文地址:https://www.cnblogs.com/-beyond/p/10498808.html
Copyright © 2011-2022 走看看