springboot项目中定时任务如何优雅退出
在一个springboot项目中需要跑定时任务处理批数据时,突然有个Kill命令或者一个Ctrl+C的命令,此时我们需要当批数据处理完毕后才允许定时任务关闭,也就是当定时任务结束时才允许Kill命令生效。
启动类
启动类上我们获取到相应的上下文,捕捉相应命令。在这里插入代码片
@SpringBootApplication
/**指定mapper对应包的路径*/
@MapperScan("com.youlanw.kz.dao")
/**开启计划任务*/
@EnableScheduling
/**开启异常重试机制*/
@EnableRetry
public class YlkzTaskApplication {
public static ConfigurableApplicationContext context;
public static void main(String[] args) {
context = SpringApplication.run(YlkzTaskApplication.class, args);
/**
* 捕捉命令实现优雅退出
*/
MySignalHandler.install("TERM"); //捕捉kill命令
MySignalHandler.install("INT"); //捕捉ctrl+c命令
}
}
优雅退出配置类
通过install方法捕捉到相应的命令,
通过signalAction方法进行总开发的控制。
import org.slf4j.LoggerFactory;
import sun.misc.Signal;
import sun.misc.SignalHandler;
/**
* @description: 定时任务控制类(实现优雅退出)
* @method:
* @author: mamengmeng
* @date: 10:51 2018/8/13
*/
public class MySignalHandler implements SignalHandler {
private final static org.slf4j.Logger logger = LoggerFactory.getLogger(MySignalHandler.class);
private SignalHandler oldHandler;
/**
* 定时任务总开关-状态:true:打开 false:关闭
*/
public 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 {
//关闭总开关
this.base_flag = false;
logger.info("\n执行优雅退出操作\n等待运行中任务执行完毕…………");
Thread.sleep(3000);
StringBuffer stringBuffer = new StringBuffer("a");
//此处为相关的业务代码,只要还有一个定时任务在执行,那么就等待线程任务执行完毕。
while (BaseApplyTask.apply_flag || BaseResumeTask.resume_flag || CorpDemandTask.demand_flag || RecommendResumeTask.resume_flag || BaseCodeTask.code_flag || RecommendoneTask.resume_flag ||ResumeByZcbTask.zpbresume_flag) {
//等待线程任务执行完毕
stringBuffer.append("");
}
//获取到的上下文对象关闭相应的程序。
YlkzTaskApplication.context.close();
logger.info("\n================\n程序已安全退出!\n================");
oldHandler.handle(signal);
} catch (Exception e) {
logger.error("handle|Signal handler" + "failed, reason "
+ e.getMessage());
e.printStackTrace();
}
}
}
举例说明
我们在定时任务中添加一个总开关,当总开关是关着时是不允许定时任务执行的,
@Component
public class BaseCodeTask {
private final static Logger logger = LoggerFactory.getLogger(BaseCodeTask.class);
@Autowired
private ResumeService resumeService;
public static boolean code_flag = true; //简历任务执行状态 true:执行中 false:执行完毕
private static final Integer LIMIT = 500;
private final static long time = 60 * 1000; //一分钟
/**
* @param
* @description: 同步简历信息(定时任务)
* 任务执行间隔时间:6秒
* 待同步数据为空,则5分钟后执行下一次
* @method: sendResume
* @author: zhengmingjie
* @date: 16:17 2018/8/3
* @return: void
*/
@Scheduled(initialDelay = 1000, fixedDelay = time / 10)
@Async
public void sendResume() throws Exception {
List<Resume> list = null;
try {
//总开关状态:true:打开 false:关闭
if (!MySignalHandler.base_flag)
return;
this.code_flag = true;
logger.info("\n======定时任务:初始化基本数据======\n开始执行\n");
//以下是业务代码。相关的定时任务批处理
resumeService.initializationMap();
resumeService.setCodeDictionary();
resumeService.setCityInfo();
resumeService.setCodePostInfo();
logger.info("\n======定时任务:初始化基本数据======\n结束\n");
} catch (Exception e) {
e.printStackTrace();
} finally {
this.code_flag = false;
}
}
}
定时任务优雅退出的使用可以有效的防止批处理任务的中断,小伙伴们可以尝试添加哦。。。。
版权声明:本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 举报,一经查实,本站将立刻删除。
文章由极客之音整理,本文链接:https://www.bmabk.com/index.php/post/80406.html