spring 中schedule注解方式实现定时任务

定时任务是常用功能,比如超时检索等数据检索功能或者定时发布功能,使用spring boot 注解式代码如下:

① 在 main 中开启定时任务的注解 @EnableScheduling

package com.jiangcheng;

import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.scheduling.annotation.EnableScheduling;

@EnableScheduling   //开启定时任务注解
@SpringBootApplication
public class TaskApplication {

    public static void main(String[] args) {
        SpringApplication.run(TaskApplication.class, args);
    }
}


②在 Service 中编写定时任务 @Scheduled

package com.jiangcheng.service;

import java.util.Date;

import org.springframework.scheduling.annotation.Scheduled;
import org.springframework.stereotype.Service;

@Service
public class TaskService {

    /**
     * second(秒), minute(分), hour(时), day of month(日), month(月), day of week(周几).
     * 例子:
     *  【0 0/5 14,18 * * ?】 每天14点整,和18点整,每隔5分钟执行一次
     *  【0 15 10 ? * 1-6】 每个月的周一至周六10:15分执行一次
     *  【0 0 2 ? * 6L】每个月的最后一个周六凌晨2点执行一次
     *  【0 0 2 LW * ?】每个月的最后一个工作日凌晨2点执行一次
     *  【0 0 2-4 ? * 1#1】每个月的第一个周一凌晨2点到4点期间,每个整点都执行一次;
     */
    @Scheduled(cron = "0,1,2,3,4 * * * * MON-SAT")
    public void runTask(){
        System.out.println(new Date()+"超时锁定");
    }
}


③ Maven 依赖

<dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-parent</artifactId>
        </dependency>

使用spring注解方式优势是使用简单,劣势是不支持分布式。要实现分布式需要进行改动使多个服务访问同一资源判断其他服务是否已经执行过定时任务,如下方式改造第二步中方法:

private static String serverIp = null;
 
    static {
        //获取服务器的IP地址,便于后续追踪
        try {
            InetAddress address = InetAddress.getLocalHost();
            serverIp = address.getHostAddress();
        } catch (Exception e) {
            logger.error("获取服务器IP地址有误!!");
            e.printStackTrace();
        }
    }

   /**
     * second(秒), minute(分), hour(时), day of month(日), month(月), day of week(周几).
     * 例子:
     *  【0 0/5 14,18 * * ?】 每天14点整,和18点整,每隔5分钟执行一次
     *  【0 15 10 ? * 1-6】 每个月的周一至周六10:15分执行一次
     *  【0 0 2 ? * 6L】每个月的最后一个周六凌晨2点执行一次
     *  【0 0 2 LW * ?】每个月的最后一个工作日凌晨2点执行一次
     *  【0 0 2-4 ? * 1#1】每个月的第一个周一凌晨2点到4点期间,每个整点都执行一次;
     */
    @Scheduled(cron = "0,1,2,3,4 * * * * MON-SAT")
    public void runTask(){
        logger.info("job start");
        String jobName = "doTask";
        long startTime = new Date().getTime();
        try {
            if (checkTask(jobName)){
                jobMapper.doTaskSchedule();
                jobMapper.updateJobStatus(jobName,serverIp,"off");
                logger.info(jobName+"执行完成,耗时:"+(new Date().getTime()-startTime)+"毫秒!");
System.out.println(new Date()+"超时锁定");
            }
        } catch (Exception e) { 
            e.printStackTrace(); 
        }
    }
 
 
    private Boolean checkTask(String jobName) throws Exception {
        int max = 10000;
        int min = (int) Math.round(Math.random()*8000);
        long sleepTime = Math.round(Math.random()*(max-min));
        logger.info(jobName+"睡了:"+ sleepTime + "毫秒");
        Thread.sleep(sleepTime);
 
        if (jobMapper.getJobOff(jobName) == 1){
            jobMapper.updateJobStatus(jobName,serverIp,"on");
            return true;
        }
        logger.info(jobName+"已被其他服务器执行");
        return false;
    }

数据库新增表:

CREATE TABLE `job_manager` (
  `job_name` varchar(50) NOT NULL PRIMARY KEY COMMENT '名称',
  `job_desc` varchar(50)  COMMENT 'job描述',
  `server_ip` varchar(50) NOT NULL COMMENT '服务器ip',
  `on_off` varchar(10) DEFAULT 'off' COMMENT '开关(on:正在执行,off:执行完毕)',
  `update_date` datetime NOT NULL COMMENT '更新时间'
) ENGINE=InnoDB DEFAULT CHARSET=utf8 COMMENT='job管理' ROW_FORMAT=DYNAMIC;
 
 
INSERT INTO `job_manager`
VALUES
('doTask','更新doTask的job','0.0.0.0','off',now());

查询或修改任务状态上sql:

<select id="getJobOff" parameterType="string" resultType="int">
        SELECT count(1) FROM job_manager
        WHERE job_name = #{jobName} AND on_off = 'off' AND update_date < curdate()
    </select>
 
    <update id="updateJobStatus" parameterType="map">
        UPDATE job_manager
        SET on_off=#{status},server_ip=#{serverIp},update_date=now()
        WHERE job_name = #{jobName}
    </update>

 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值