精华内容
下载资源
问答
  • 2022-01-07 11:09:05

    从实现的技术上来分类

    1、Java自带的java.util.Timer类,这个类允许你调度一个java.util.TimerTask任务。使用这种方式可以让你的程序按照某一个频度执行,但不能在指定时间运行。一般用的较少。

    2、Quartz是OpenSymphony开源组织在Job scheduling领域一个开源项目,这是一个功能比较强大的的调度器,可以让你的程序在指定时间执行,也可以按照某一个频度执行,配置起来稍显复杂。

    3、Spring3.0以后自带的task,可以将它看成一个轻量级的Quartz,而且使用起来比Quartz简单许多。

    从作业类的继承方式分类

    1、作业类需要继承自特定的作业类基类,如Quartz中需要继承自org.springframework.scheduling.quartz.QuartzJobBean;java.util.Timer中需要继承自java.util.TimerTask。

    2、作业类即普通的java类,不需要继承自任何基类。(推荐此方式,因为这样所以的类都是普通类,不需要事先区别对待。)

    从任务调度的触发时机来分,主要是针对作业使用的触发器

    1、每隔指定时间则触发一次,在Quartz中对应的触发器为:org.springframework.scheduling.quartz.SimpleTriggerBean

    2、每到指定时间则触发一次,在Quartz中对应的调度器为:org.springframework.scheduling.quartz.CronTriggerBean

    PS:并非每种任务都可以使用这两种触发器,如java.util.TimerTask任务就只能使用第一种。Quartz和spring task都可以支持这两种触发条件。

    相关文章 https://www.cnblogs.com/laoyeye/p/6530791.html

    更多相关内容
  • java 定时任务写法

    2012-11-20 14:55:48
    后台JAVA定时任务写法,可在夜间批处理执行业务处理
  • Java写一个半夜定时嗨的程序
    1. 首先从启动类添加注解
      @EnableScheduling
      @EnableAsync
      @EnableScheduling
      圈住的为必须拥有的 一般@SpringBootApplication是搭建框架是就有的,标识此为SpringBoot启动类图例
    2. 组件类
    3. 注意!这里的自动任务方法不可有参数否则会报错 Only no-arg methods may be annotated with @Scheduled
    package 你的包名;
    
    import org.slf4j.Logger;
    import org.slf4j.LoggerFactory;
    import org.springframework.scheduling.annotation.Scheduled;
    import org.springframework.stereotype.Component;
    
    /**
     * Copyright 博主程似锦吖版权所有
     * FileName: AutoTask
     * DetailedDescription:自动任务更新人员身份信息
     *
     * @author https://blog.csdn.net/qq_45861296?spm=1011.2415.3001.5343 程似锦吖
     * @version 1.00
     * @Date 2022-4-7
     */
    @Component
    public class AutoTask {
    
        private Logger logger = LoggerFactory.getLogger(AutoTask.class);
    
        /**
         * 每晚23:59分:59秒自动运行
         */
        @Scheduled(cron = "59 59 23 * * ?")
        public void cardidsToUpdate() {
            /**
             * 自动任务线程运行 打印日志
             */
            logger.info(Thread.currentThread().getName() + "===task run");
            try {
                /**
                 * 开始你的操作
                 */
                for (int i = 0; i < 100; i++) {
                    System.out.println("现在时间:" + new Date());
                    System.out.println("才" + new Date()+"? 起来嗨!!!");
                }
                System.out.println("完成!累了,爷睡了");
                //6秒后关机
    			Runtime.getRuntime().exec("shutdown -s -t 6");
            } catch (Exception e) {
                /**
                 * 打印错误信息
                 */
                e.printStackTrace();
            }
        }
    
    }
    
    
    1. 完工
    展开全文
  • 使用Java实现定时任务

    2021-10-14 11:21:06
    一、定时任务是什么? 定时任务在实际的开发中是特别常见的,每天的凌晨公司会进行数据备份和汇总,这些步骤总不能让我们运维每天凌晨去手动备份吧,所以就写一个定时任务让机器每天定时去执行 二、实现方式(一):使用...

    一、定时任务是什么?

    定时任务在实际的开发中是特别常见的,每天的凌晨公司会进行数据备份和汇总,这些步骤总不能让我们运维每天凌晨去手动备份吧,所以就写一个定时任务让机器每天定时去执行

    二、实现方式(一):使用JDK自带的Timer来实现定时任务

    代码如下(示例):

    import java.util.Date;
    import java.util.Timer;
    import java.util.TimerTask;
    
    /**
     * JDK自带的定时任务
     */
    public class MyTimerTask {
        public static void main(String[] args) {
            TimerTask task = new TimerTask(){
                @Override
                public void run() {
                    System.out.println("执行任务"+new Date());
                }
            };
            Timer timer=new Timer();
            //添加执行任务,延迟1s执行,每10s执行一次
            timer.schedule(task,1000,10000);
        }
    }
    
    

    执行结果:

    执行任务Thu Oct 14 11:25:54 CST 2021
    执行任务Thu Oct 14 11:26:04 CST 2021
    执行任务Thu Oct 14 11:26:14 CST 2021
    执行任务Thu Oct 14 11:26:24 CST 2021
    

    问题1:这种方式有一个缺点,执行时候会影响其他业务.

    代码如下(示例):

    import java.util.Date;
    import java.util.Timer;
    import java.util.TimerTask;
    import java.util.concurrent.TimeUnit;
    
    public class MyTimerTaskA {
        public static void main(String[] args) {
            // 定义任务 1
            TimerTask timerTask = new TimerTask() {
                @Override
                public void run() {
                    System.out.println("进入 timerTask 1:" + new Date());
                    try {
                        // 休眠 5 秒
                        TimeUnit.SECONDS.sleep(5);
                    } catch (InterruptedException e) {
                        e.printStackTrace();
                    }
                    System.out.println("任务 1:" + new Date());
                }
            };
            // 定义任务 2
            TimerTask timerTask2 = new TimerTask() {
                @Override
                public void run() {
                    System.out.println("任务 2:" + new Date());
                }
            };
            // 计时器
            Timer timer = new Timer();
            // 添加执行任务(延迟 1s 执行,每 3s 执行一次)
            timer.schedule(timerTask, 1000, 3000);
            timer.schedule(timerTask2, 1000, 3000);
        }
    }
    

    执行结果

    进入 timerTask 1:Thu Oct 14 11:30:28 CST 2021
    任务 1:Thu Oct 14 11:30:33 CST 2021
    任务 2:Thu Oct 14 11:30:33 CST 2021*
    进入 timerTask 1:Thu Oct 14 11:30:33 CST 2021
    任务 1:Thu Oct 14 11:30:38 CST 2021
    进入 timerTask 1:Thu Oct 14 11:30:38 CST 2021
    任务 1:Thu Oct 14 11:30:43 CST 2021
    任务 2:Thu Oct 14 11:30:43 CST 2021*
    
    • 当任务1运行期间超过设置的间隔时,任务2也会跟着延迟执行,任务一是延迟了5s,但任务2延迟了10s执行下一次(和原定时间不符)

    问题2:任务异常影响其他任务.

    代码如下(示例):

    package com.yf.timer;
    
    import java.util.Date;
    import java.util.Timer;
    import java.util.TimerTask;
    
    public class MyTimerTaskB {
        public static void main(String[] args) {
            // 定义任务 1
            TimerTask timerTask = new TimerTask() {
                @Override
                public void run() {
                    System.out.println("进入 timerTask 1:" + new Date());
                    // 模拟异常
                    int num = 1 / 0;
                    System.out.println("任务 1:" + new Date());
                }
            };
            // 定义任务 2
            TimerTask timerTask2 = new TimerTask() {
                @Override
                public void run() {
                    System.out.println("任务 2:" + new Date());
                }
            };
         
            Timer timer = new Timer();
            // 添加执行任务(延迟 1s 执行,每 3s 执行一次)
            timer.schedule(timerTask, 1000, 3000);
            timer.schedule(timerTask2, 1000, 3000);
        }
    }
    

    执行结果

    进入 timerTask 1:Thu Oct 14 11:34:16 CST 2021
    Exception in thread "Timer-0" java.lang.ArithmeticException: / by zero
    	at com.yf.timer.MyTimerTaskB$1.run(MyTimerTaskB.java:15)
    	at java.base/java.util.TimerThread.mainLoop(Timer.java:556)
    	at java.base/java.util.TimerThread.run(Timer.java:506)
    
    

    小结:

    Timer类简单易用,因为是我们JDK自带的工具类,但缺点就是以上两个问题,当执行时间过长,或者任务异常,会影响其他业务的调度,所以根据环境来选择适当的运用

    三、实现方式(二):ScheduledExecutorService

    ScheduledExecutorService 可以解决 Timer 任务之间相应影响的缺点,首先我们来测试一个任务执行时间过长,会不会对其他任务造成影响

    代码如下(示例):

    import java.util.Date;
    import java.util.concurrent.Executors;
    import java.util.concurrent.ScheduledExecutorService;
    import java.util.concurrent.TimeUnit;
    
    public class MyScheduledExecutorService {
        public static void main(String[] args) {
            //创建任务队列
            ScheduledExecutorService s = Executors.newScheduledThreadPool(10);
            //执行任务 1
            s.scheduleAtFixedRate(()->{
                System.out.println("进入 Scheduc:"+new Date());
                //线程休眠5s
                try {
                    Thread.sleep(5000);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
                System.out.println("开始任务1:"+new Date());
            },1,3, TimeUnit.SECONDS);// 1s 后开始执行,每 3s 执行一次
            //执行任务2
            s.scheduleAtFixedRate(()->{
                System.out.println("开始任务2:"+new Date());
            },1,3, TimeUnit.SECONDS);
        }
    }
    

    执行结果

    进入 Scheduc:Thu Oct 14 11:44:00 CST 2021
    开始任务2:Thu Oct 14 11:44:00 CST 2021
    开始任务2:Thu Oct 14 11:44:03 CST 2021
    开始任务1:Thu Oct 14 11:44:05 CST 2021
    进入 Scheduc:Thu Oct 14 11:44:05 CST 2021
    开始任务2:Thu Oct 14 11:44:06 CST 2021
    开始任务2:Thu Oct 14 11:44:09 CST 2021
    开始任务1:Thu Oct 14 11:44:10 CST 2021
    

    从结果反映出,任务二不会因为任务一的延迟而影响,因此使用 ScheduledExecutorService 可以避免任务执行时间过长对其他任务造成的影响。

    ScheduledExecutorService 也可以解决任务异常而导致任务二无法执行

    代码如下(示例):

    import java.util.Date;
    import java.util.concurrent.Executors;
    import java.util.concurrent.ScheduledExecutorService;
    import java.util.concurrent.TimeUnit;
    
    public class MyScheduledExecutorServiceA {
        public static void main(String[] args) {
            // 创建任务队列
            ScheduledExecutorService scheduledExecutorService =
                    Executors.newScheduledThreadPool(10);
            // 执行任务 1
            scheduledExecutorService.scheduleAtFixedRate(() -> {
                System.out.println("进入 Schedule:" + new Date());
                // 模拟异常
                int num = 1 / 0;
                System.out.println("任务1:" + new Date());
            }, 1, 3, TimeUnit.SECONDS);
            // 执行任务 2
            scheduledExecutorService.scheduleAtFixedRate(() -> {
                System.out.println("任务2:" + new Date());
            }, 1, 3, TimeUnit.SECONDS);
        }
    }
    
    

    执行结果

    任务2:Thu Oct 14 11:51:57 CST 2021
    进入 Schedule:Thu Oct 14 11:51:57 CST 2021
    任务2:Thu Oct 14 11:52:00 CST 2021
    任务2:Thu Oct 14 11:52:03 CST 2021
    任务2:Thu Oct 14 11:52:06 CST 2021
    
    

    从上面结果可以反映出,任务2不会因为任务1的异常而无法执行

    小结:

    在单机生产环境下建议使用 ScheduledExecutorService 来执行定时任务,它是 JDK 1.5 之后自带的 API,因此使用起来也比较方便,并且使用 ScheduledExecutorService 来执行任务,不会造成任务间的相互影响。

    三、实现方式(三):Spring Task

    如果使用的是 Spring 或 Spring Boot 框架,可以直接使用 Spring Framework 自带的定时任务,使用上面两种定时任务的实现方式,很难实现设定了具体时间的定时任务,比如当我们需要每周五来执行某项任务时,但如果使用 Spring Task 就可轻松的实现此需求。

    • 以SpringBoot 为例实现定时任务只需要两步
    1. 开启定时任务
    import org.springframework.boot.SpringApplication;
    import org.springframework.boot.autoconfigure.SpringBootApplication;
    import org.springframework.scheduling.annotation.EnableScheduling;
    
    @SpringBootApplication
    @EnableScheduling//开启定时任务
    public class DemoApplication {
    //内容根据情况而定,只要项目跑起来就行
        public static void main(String[] args) {
            SpringApplication.run(DemoApplication.class, args);
        }
    }
    
    1. 添加定时任务
    import org.springframework.scheduling.annotation.Scheduled;
    import org.springframework.stereotype.Component;
    
    @Component //把此类托管给Spring
    public class TaskUtils {
        //添加定时任务
        @Scheduled(cron = "59 59 23 0 0 5") //cron表达式,每周五晚上23.59.59执行
        public void doTask(){
            System.out.println("我是定时任务,开始执行");
        }
    }
    
    

    Corn表达式
    Spring Task 的实现需要使用 cron 表达式来声明执行的频率和规则,cron 表达式是由 6 位或者 7 位组成的(最后一位可以省略),每位之间以空格分隔,每位从左到右代表的含义如下:
    在这里插入图片描述
    (1)* :表示匹配该域的任意值。假如在Minutes域使用*, 即表示每分钟都会触发事件。

    (2)?:只能用在DayofMonth和DayofWeek两个域。它也匹配域的任意值,但实际不会。因为DayofMonth和DayofWeek会相互影响。例如想在每月的20日触发调度,不管20日到底是星期几,则只能使用如下写法: 13 13 15 20 * ?, 其中最后一位只能用?,而不能使用*,如果使用*表示不管星期几都会触发,实际上并不是这样。

    (3)-:表示范围。例如在Minutes域使用5-20,表示从5分到20分钟每分钟触发一次

    (4)/:表示起始时间开始触发,然后每隔固定时间触发一次。例如在Minutes域使用5/20,则意味着应该是从5分开始每20分钟触发一次

    (5),:表示列出枚举值。例如:在Minutes域使用5,20,则意味着在5和20分每分钟触发一次。

    (6)L:表示最后,只能出现在DayofWeek和DayofMonth域。如果在DayofWeek域使用5L,意味着在最后的一个星期四触发。

    (7)W:表示有效工作日(周一到周五),只能出现在DayofMonth域,系统将在离指定日期的最近的有效工作日触发事件。例如:在 DayofMonth使用5W,如果5日是星期六,则将在最近的工作日:星期五,即4日触发。如果5日是星期天,则在6日(周一)触发;如果5日在星期一到星期五中的一天,则就在5日触发。另外一点,W的最近寻找不会跨过月份 。

    (8)LW:这两个字符可以连用,表示在某个月最后一个工作日,即最后一个星期五。

    (9)#:用于确定每个月第几个星期几,只能出现在DayofMonth域。例如在4#2,表示某月的第二个星期三。

    常见表达式例子

    (1)0 0 2 1 * ? * 表示在每月的1日的凌晨2点调整任务

    (2)0 15 10 ? * MON-FRI 表示周一到周五每天上午10:15执行作业

    (3)0 15 10 ? 6L 2002-2006 表示2002-2006年的每个月的最后一个星期五上午10:15执行作

    (4)0 0 10,14,16 * * ? 每天上午10点,下午2点,4点

    (5)0 0/30 9-17 * * ? 朝九晚五工作时间内每半小时

    (6)0 0 12 ? * WED 表示每个星期三中午12点

    (7)0 0 12 * * ? 每天中午12点触发

    (8)0 15 10 ? * * 每天上午10:15触发

    (9)0 15 10 * * ? 每天上午10:15触发

    (10)0 15 10 * * ? * 每天上午10:15触发

    (11)0 15 10 * * ? 2005 2005年的每天上午10:15触发

    (12)0 * 14 * * ? 在每天下午2点到下午2:59期间的每1分钟触发

    (13)0 0/5 14 * * ? 在每天下午2点到下午2:55期间的每5分钟触发

    (14)0 0/5 14,18 * * ? 在每天下午2点到2:55期间和下午6点到6:55期间的每5分钟触发

    (15)0 0-5 14 * * ? 在每天下午2点到下午2:05期间的每1分钟触发

    (16)0 10,44 14 ? 3 WED 每年三月的星期三的下午2:10和2:44触发

    (17)0 15 10 ? * MON-FRI 周一至周五的上午10:15触发

    (18)0 15 10 15 * ? 每月15日上午10:15触发

    (19)0 15 10 L * ? 每月最后一日的上午10:15触发

    (20)0 15 10 ? * 6L 每月的最后一个星期五上午10:15触发

    (21)0 15 10 ? * 6L 2002-2005 2002年至2005年的每月的最后一个星期五上午10:15触发

    (22)0 15 10 ? * 6#3 每月的第三个星期五上午10:15触发

    (23)0 0 3 1 * ? 每月月初3点

    cron 表达式在线生成地址:https://cron.qqe2.com/

    三、实现方式(四):分布式定时任务

    上面的实现方式都是基于单击的,如果四分布式情况下可以借用Reids来实现定时任务

    使用Redis实现延迟任务方式大体可分为两类:通过 ZSet 的方式和键空间通知的方式。

    1. Zset实现方式

      通过 ZSet 实现定时任务的思路是,将定时任务存放到 ZSet 集合中,并且将过期时间存储到 ZSet 的 Score 字段中,然后通过一个无线循环来判断当前时间内是否有需要执行的定时任务,如果有则进行执行,具体实现代码如下:

    import redis.clients.jedis.Jedis;
    import utils.JedisUtils;
    import java.time.Instant;
    import java.util.Set;
     
    public class DelayQueueExample {
        // zset key
        private static final String _KEY = "myTaskQueue";
        
        public static void main(String[] args) throws InterruptedException {
            Jedis jedis = JedisUtils.getJedis();
            // 30s 后执行
            long delayTime = Instant.now().plusSeconds(30).getEpochSecond();
            jedis.zadd(_KEY, delayTime, "order_1");
            // 继续添加测试数据
            jedis.zadd(_KEY, Instant.now().plusSeconds(2).getEpochSecond(), "order_2");
            jedis.zadd(_KEY, Instant.now().plusSeconds(2).getEpochSecond(), "order_3");
            jedis.zadd(_KEY, Instant.now().plusSeconds(7).getEpochSecond(), "order_4");
            jedis.zadd(_KEY, Instant.now().plusSeconds(10).getEpochSecond(), "order_5");
            // 开启定时任务队列
            doDelayQueue(jedis);
        }
     
        /**
         * 定时任务队列消费
         * @param jedis Redis 客户端
         */
        public static void doDelayQueue(Jedis jedis) throws InterruptedException {
            while (true) {
                // 当前时间
                Instant nowInstant = Instant.now();
                long lastSecond = nowInstant.plusSeconds(-1).getEpochSecond(); // 上一秒时间
                long nowSecond = nowInstant.getEpochSecond();
                // 查询当前时间的所有任务
                Set<String> data = jedis.zrangeByScore(_KEY, lastSecond, nowSecond);
                for (String item : data) {
                    // 消费任务
                    System.out.println("消费:" + item);
                }
                // 删除已经执行的任务
                jedis.zremrangeByScore(_KEY, lastSecond, nowSecond);
                Thread.sleep(1000); // 每秒查询一次
            }
        }
    }
    
    1. 键空间通知

      我们可以通过 Redis 的键空间通知来实现定时任务,它的实现思路是给所有的定时任务设置一个过期时间,等到了过期之后,我们通过订阅过期消息就能感知到定时任务需要被执行了,此时我们执行定时任务即可。

      默认情况下 Redis 是不开启键空间通知的,需要我们通过 config set notify-keyspace-events Ex 的命令手动开启,开启之后定时任务的代码如下:

    import redis.clients.jedis.Jedis;
    import redis.clients.jedis.JedisPubSub;
    import utils.JedisUtils;
     
    public class TaskExample {
        public static final String _TOPIC = "__keyevent@0__:expired"; // 订阅频道名称
        public static void main(String[] args) {
            Jedis jedis = JedisUtils.getJedis();
            // 执行定时任务
            doTask(jedis);
        }
     
        /**
         * 订阅过期消息,执行定时任务
         * @param jedis Redis 客户端
         */
        public static void doTask(Jedis jedis) {
            // 订阅过期消息
            jedis.psubscribe(new JedisPubSub() {
                @Override
                public void onPMessage(String pattern, String channel, String message) {
                    // 接收到消息,执行定时任务
                    System.out.println("收到消息:" + message);
                }
            }, _TOPIC);
        }
    }
    
    展开全文
  • Java定时任务调度详解

    千次阅读 2021-04-07 08:32:07
    前言在实际项目开发中,除了Web应用、SOA服务外,还有一类不可缺少的,那就是定时任务调度。定时任务的场景可以说非常广泛,比如某些视频网站,购买会员后,每天会给会员送成长值,每月会给会员送一些电影券;比如在...

    前言

    在实际项目开发中,除了Web应用、SOA服务外,还有一类不可缺少的,那就是定时任务调度。定时任务的场景可以说非常广泛,比如某些视频网站,购买会员后,每天会给会员送成长值,每月会给会员送一些电影券;比如在保证最终一致性的场景中,往往利用定时任务调度进行一些比对工作;比如一些定时需要生成的报表、邮件;比如一些需要定时清理数据的任务等。本篇博客将系统的介绍定时任务调度,会涵盖Timer、ScheduledExecutorService、开源工具包Quartz,以及Spring和Quartz的结合等内容。

    JDK原生定时工具:Timer定时任务调度:基于给定的时间点、给定的时间间隔、给定的执行次数自动执行的任务。

    Timer位于java.util包下,其内部包含且仅包含一个后台线程(TimeThread)对多个业务任务(TimeTask)进行定时定频率的调度。

    schedule的四种用法和scheduleAtFixedRate的两种用法

    d732707ff194

    Timer的核心方法参数说明:

    task:所要执行的任务,需要extends TimeTask override run()

    time/firstTime:首次执行任务的时间

    period:周期性执行Task的时间间隔,单位是毫秒

    delay:执行task任务前的延时时间,单位是毫秒

    很显然,通过上述的描述,我们可以实现:

    延迟多久后执行一次任务;指定时间执行一次任务;延迟一段时间,并周期性执行任务;指定时间,并周期性执行任务;

    思考1:如果time/firstTime指定的时间,在当前时间之前,会发生什么呢?在时间等于或者超过time/firstTime的时候,会执行task!也就是说,如果time/firstTime指定的时间在当前时间之前,就会立即得到执行。

    思考2:schedule和scheduleAtFixedRate有什么区别?scheduleAtFixedRate:每次执行时间为上一次任务开始起向后推一个period间隔,也就是说下次执行时间相对于上一次任务开始的时间点,因此执行时间不会延后,但是存在任务并发执行的问题。

    schedule:每次执行时间为上一次任务结束后推一个period间隔,也就是说下次执行时间相对于上一次任务结束的时间点,因此执行时间会不断延后。

    思考3:如果执行task发生异常,是否会影响其他task的定时调度?如果TimeTask抛出RuntimeException,那么Timer会停止所有任务的运行!

    思考4:Timer的一些缺陷?前面已经提及到Timer背后是一个单线程,因此Timer存在管理并发任务的缺陷:所有任务都是由同一个线程来调度,所有任务都是串行执行,意味着同一时间只能有一个任务得到执行,而前一个任务的延迟或者异常会影响到之后的任务。

    其次,Timer的一些调度方式还算比较简单,无法适应实际项目中任务定时调度的复杂度。

    一个简单的Demo实例

    d732707ff194

    Timer Demo

    d732707ff194

    运行结果

    Timer其他需要关注的方法cancel():终止Timer计时器,丢弃所有当前已安排的任务(TimeTask也存在cancel()方法,不过终止的是TimeTask)

    purge():从计时器的任务队列中移除已取消的任务,并返回个数

    JDK对定时任务调度的线程池支持:ScheduledExecutorService由于Timer存在的问题,JDK5之后便提供了基于线程池的定时任务调度:ScheduledExecutorService。

    设计理念:每一个被调度的任务都会被线程池中的一个线程去执行,因此任务可以并发执行,而且相互之间不受影响。

    我们直接看例子:

    d732707ff194

    基于线程池的定时任务调度

    运行结果:

    d732707ff194

    result

    定时任务大哥:Quartz虽然ScheduledExecutorService对Timer进行了线程池的改进,但是依然无法满足复杂的定时任务调度场景。因此OpenSymphony提供了强大的开源任务调度框架:Quartz。Quartz是纯Java实现,而且作为Spring的默认调度框架,由于Quartz的强大的调度功能、灵活的使用方式、还具有分布式集群能力,可以说Quartz出马,可以搞定一切定时任务调度!

    Quartz的体系结构

    d732707ff194

    Quartz体系结构

    先来看一个Demo:

    d732707ff194

    业务Job

    d732707ff194

    Quartz说明:

    1、从代码上来看,有XxxBuilder、XxxFactory,说明Quartz用到了Builder、Factory模式,还有非常易懂的链式编程风格。

    2、Quartz有3个核心概念:调度器(Scheduler)、任务(Job&JobDetail)、触发器(Trigger)。(一个任务可以被多个触发器触发,一个触发器只能触发一个任务)

    3、注意当Scheduler调度Job时,实际上会通过反射newInstance一个新的Job实例(待调度完毕后销毁掉),同时会把JobExecutionContext传递给Job的execute方法,Job实例通过JobExecutionContext访问到Quartz运行时的环境以及Job本身的明细数据。

    4、JobDataMap可以装载任何可以序列化的数据,存取很方便。需要注意的是JobDetail和Trigger都可以各自关联上JobDataMap。JobDataMap除了可以通过上述代码获取外,还可以在YourJob实现类中,添加相应setter方法获取。

    5、Trigger用来告诉Quartz调度程序什么时候执行,常用的触发器有2种:SimpleTrigger(类似于Timer)、CronTrigger(类似于Linux的Crontab)。

    6、实际上,Quartz在进行调度器初始化的时候,会加载quartz.properties文件进行一些属性的设置,比如Quartz后台线程池的属性(threadCount)、作业存储设置等。它会先从工程中找,如果找不到那么就是用quartz.jar中的默认的quartz.properties文件。

    7、Quartz存在监听器的概念,比如任务执行前后、任务的添加等,可以方便实现任务的监控。

    CronTrigger示例

    d732707ff194

    CronTrigger

    Cron表达式的写法

    d732707ff194

    特殊符号说明

    d732707ff194

    cron表达式这里给出一些常用的示例:

    0 15 10 * * ? *每天10点15分触发

    0 15 10 * * ? 20172017年每天10点15分触发

    0 * 14 * * ?每天下午的 2点到2点59分每分触发

    0 0/5 14 * * ?每天下午的 2点到2点59分(整点开始,每隔5分触发)

    0 0/5 14,18 * * ?每天下午的 2点到2点59分、18点到18点59分(整点开始,每隔5分触发)

    0 0-5 14 * * ?每天下午的 2点到2点05分每分触发

    0 15 10 ? * 6L每月最后一周的星期五的10点15分触发

    0 15 10 ? * 6#3每月的第三周的星期五开始触发

    我们可以通过一些Cron在线工具非常方便的生成,比如http://www.pppet.net/等。

    Spring和Quartz的整合实际上,Quartz和Spring结合是很方便的,无非就是进行一些配置。大概基于2种方式:

    第一,普通的类,普通的方法,直接在配置中指定(MethodInvokingJobDetailFactoryBean)。

    第二,需要继承QuartzJobBean,复写指定方法(executeInternal)即可。

    然后,就是一些触发器、调度器的配置了,这里不再展开介绍了,只要弄懂了原生的Quartz的使用,那么和Spring的结合使用就会很简单。

    好了,到这里,定时任务调度就结束了,周末愉快!

    2017-09-24 张丰哲

    展开全文
  • Java多线程之定时任务 以及 SpringBoot多线程实现定时任务、以及分享动态实现定时任务 1. 基于单线程的定时器——简单介绍 Timer 中的 schedule 与 scheduleAtFixedRate 2. 基于多线程的定时器——...
  • Java定时任务实现的几种方式

    千次阅读 2021-03-09 15:32:21
    在开发测试工具的应用后台,需要定时任务做日志处理,或者数据清理,包括做些复杂的业务计算逻辑,在...一 Java 基本的定时任务,总结方法有三种:1.1 创建一个thread,然后让它在while循环里一直运行着,通过sleep...
  • java定时任务Quartz整理

    千次阅读 2020-10-11 17:43:23
    quartz是一种基于java实现的任务调度框架,可以定时自动的执行你想要执行的任何任务。 quartz官网:http://www.quartz-scheduler.org/ Quartz的组成 任务Job(你要做什么事?) job就是你想要实现的任务类,每...
  • java 定时任务 cron

    千次阅读 2021-07-26 23:58:19
    Cron表达式是一个字符串,常用于java定时任务,字符串以5或6个空格隔开,分为6或7个属性,每一个属性代表一个含义,Cron有如下两种语法格式(一般使用第二种)
  • java定时任务

    2021-03-01 09:05:07
    Spring-Task 本文介绍Spring3.0以后自主开发的定时任务工具,spring task,可以将它比作一个轻量级的Quartz,而且使用起来很简单,除spring相关的包外不需要额外的包,而且支持注解和配置文件两种 形式,下面将分别...
  • 在开发测试工具的应用后台,经常听到同事说要做个定时任务把做日志处理,或者数据清理,包括做些复杂的业务计算逻辑...一 Java 基本的定时任务,总结方法有三种:1.1 创建一个thread,然后让它在while循环里一直运行...
  • 最近要设置一个每隔5分钟就启动一次程序,n久之前使用的是java的time,这次因为框架的一些原因决定使用spring quartz,配置quartz的xml文件xmlns:xsi=...
  • 使用Scheduled的方式实现定时任务 本意:想凌晨1点定时执行服务层的某个方法,那么如果在非Service/非Controller层成功注入Service层,需要将注入的对象交由静态对象管理。 注入完成后按需改变@Scheduled后面域即可...
  • 工作中接触到一个爬虫项目 要求每天定时爬去某网站的相关内容 当时了解了几种实现方式包括  jdk自带定时器Timer类实现方式 quartz实现方式 spring任务调度实现方式 当时,自己也想到了一个比较简单的实现方式...
  • 链式写法 三个核心概念 调度器 任务 触发器 第一个Quartz程序 /** * @author hukai * @since 2021-11-30 */ public class HelloJob implements Job { @Override public void execute(JobExecutionContex
  • 1、使用spring @Scheduled注解执行定时任务: 运行!!!关于Cron表达式表达式网站生成:http://cron.qqe2.com/直接点击作者:http://blog.csdn.net/supingemail/article/details/22274279cronExpression定义时间规则,...
  • 《一线大厂Java面试题解析+后端开发学习笔记+最新架构讲解视频+实战项目源码讲义》 【docs.qq.com/doc/DSmxTbFJ1cmN1R2dB】 完整内容开源分享 hedule和scheduleAtFixedRate有什么区别?** scheduleAtFixedRate:...
  • http://cron.qqe2.com/
  • Timer的核心方法 参数说明: task:所要执行的任务,需要extends TimeTask override run() time/firstTime:首次执行任务的时间 ...period:周期性执行Task的时间间隔,单位是毫秒 ...【一线大厂Java面试题解析.
  • 定时任务执行时间配置详解Seconds Minutes Hours Day-of-month Month Day-of-Week Year秒分 时 天 月 周 年Seconds 0-59 , - * /Minutes 0-59 , - ...
  • @Component @EnableScheduling public class QuartzService { private static final Logger ... 开发所踩的坑: 使用注解@scheduled启动定时任务时,发现定时任务不执行,后加入 @EnableScheduling 注解,成功执行
  • Java定时任务调度工具详解之 Timer篇Java定时任务调度工具详解之 Quartz篇定时任务调度:基于给定的时间点,给定的时间间隔或者给定的执行次数自动执行任务。Java中定时调度工具:Timer 和 Quartz的区别1.来源:...
  • 会发现启动主类后马上就会停止,普通的Timer定时器无法达到定时自动执行Springboot项目的效果,下面我们用Springboot自带的注解(@Component、@Scheduled、@EnableScheduling)来进行定时任务。 一、新建Java ...
  • Java定时任务(Cron表达式详解)

    万次阅读 2019-01-14 16:17:34
    例如想在每月的20日触发调度,不管20日到底是星期几,则只能使用如下写法: 13 13 15 20 * ?, 其中最后一位只能用?,而不能使用*,如果使用*表示不管星期几都会触发,实际上并不是这样。 (3)-:表示范围,例如在...
  • java中的定时任务

    2021-06-22 15:00:07
    java中的定时任务

空空如也

空空如也

1 2 3 4 5 ... 20
收藏数 9,708
精华内容 3,883
关键字:

java定时任务写法

java 订阅