Spring中的@Scheduled可以进行定时任务开发,定时执行方法。
1、先在yml中配置定时任务的开关,false默认是关闭,true是开启
subway:
# 定时任务开关
EnvironmentalAlarmTask: false
2、新建一个执行类,并在执行类上加注解@EnableScheduling
,在类里面的实现方法上加注解@Scheduled
import org.springframework.scheduling.annotation.EnableScheduling;
import org.springframework.scheduling.annotation.Scheduled;
import org.springframework.stereotype.Component;
@Component
@EnableScheduling
public class EnvironmentalAlarmTask {
/**
* 任务开关
*/
@Value("${subway.EnvironmentalAlarmTask:false}")
private boolean taskOnOff;
/**
* 定时更新环境监测报警信息
* 每一分钟执行一次
*/
@Scheduled(cron = "0 0/1 * * * ?")
public void task() throws InterruptedException {
// 如果没有加下文步骤4的定时任务控制类,需用此条件执行
if(!taskOnOff) {
return;
}
// 如果加了下文步骤4的定时任务控制类,需用此条件执行,并注释掉前一个if条件
// if(!taskOnOff || !MySignalHandler.BASE_FLAG) {
// return;
// }
TaskEnum.AddEnvironmentalTask.start(); // 定时任务开始执行
try {
//TODO 此处可写业务逻辑
System.out.println("999999");
}catch (Exception e){
e.printStackTrace();
}finally {
TaskEnum.AddEnvironmentalTask.end(); // 定时任务停止执行
}
}
}
3、新建一个枚举类,来控制定时任务的开始和停止
import lombok.extern.slf4j.Slf4j;
import java.util.concurrent.atomic.AtomicBoolean;
@Slf4j
public enum TaskEnum {
AddEnvironmentalTask("更新环境监测数据中的设备信息", new AtomicBoolean(false)),
private String name;
private AtomicBoolean running;
TaskEnum(String name, AtomicBoolean running){
this.name = name;
this.running = running;
}
public void start(){
running.set(true);
}
public void end(){
running.set(false);
}
public static boolean allStop(){
for(TaskEnum task:TaskEnum.values()){
if(task.running.get()){
log.info("等待 {} 执行完毕", task.name);
return false;
}
}
return true;
}
}
4、再写一个定时任务控制类,来实现定时任务安全退出(此控制类不写,也能实现正常的定时执行任务的功能,但是为了系统安全,最好加上此控制类)
import org.slf4j.LoggerFactory;
import sun.misc.Signal;
import sun.misc.SignalHandler;
/**
* @description: 定时任务控制类(实现安全退出)
*/
public class MySignalHandler implements SignalHandler {
private final static org.slf4j.Logger logger = LoggerFactory.getLogger(MySignalHandler.class);
private SignalHandler oldHandler;
/**
* 定时任务总开关-状态:true:打开 false:关闭
*/
protected static boolean BASE_FLAG = true;
@Override
public void handle(Signal signal) {
signalAction(signal);
}
public static SignalHandler install(String signalName) {
Signal diagSignal = new Signal(signalName);
MySignalHandler instance = new MySignalHandler();
instance.oldHandler = Signal.handle(diagSignal, instance);
return instance;
}
public void signalAction(Signal signal) {
try {
BASE_FLAG = false;
logger.info("\n执行安全退出操作\n等待运行中任务执行完毕…………");
Thread.sleep(1000);
while (!TaskEnum.allStop()){
//等待线程任务执行完毕
Thread.sleep(1000);
}
//获取到的上下文对象关闭相应的程序。
//(注:SubwayDeviceApplication是我自己项目的启动类,实际应用中需将其替换成你们自己项目的启动类)
SubwayDeviceApplication.context.close();
logger.info("\n================\n程序已安全退出!\n================");
oldHandler.handle(signal);
} catch (Exception e) {
logger.error("handle|Signal handler" + "failed, reason "
+ e.getMessage());
e.printStackTrace();
}
}
}
最后把yml配置文件中的false改成true,然后再启动项目,就成功开启定时任务了。