使用Timer实现定时启动 并定时停止
需求描述 针对每个省的数据发送短信 每个省发送短信的开始时间及结束时间是动态配置的
重点为
timer的取消任务方法 只会对未运行的任务取消 不会影响到正在运行的任务,而我们需要的是将正在运行的timer线程停止 故在运行方法时声明变量 重写取消任务方法 对变量 变化 ,运行方法判断到变量 变化 停止。详细参考代码
*以下是代码片段*
/**
* 功能: 给会员发短信提醒 下月过期数量
* 需求:针对分公司配置的短信提醒规则 ,分公司配置提示时间
* 如 A机构 配置发送短信时间为 9:00-11:00
* B 为9:30-11:30
* C 为 9:20-10:20
* 则针对不同机构设置不同定时: 发送短信Timer停止发送短信定时
* 如A机构发送短信定时为 9:00 停止发送短信为11:00
* 在停止发送短信定时中 移除的发送短信定时
* @author bs
*/
public class OverdueScoreSMSAction {
private static Logger logger = Logger.getLogger(OverdueScoreSMSAction.class);
@Autowired
private OverdueScoreService overdueScoreService;
/**
* 根据机构创建 每个机构的定时
*/
public void creatSMSByCode(){
String currentTime=CurrentTime.getCurrentTime();
logger.info(currentTime+"会员过期积分短信提醒开始");
//查询需要发短信的机构
List<Object[]> listSMSOrg = overdueScoreService.findSMSOrg();
if(listSMSOrg==null || listSMSOrg.size()==0){
logger.info(currentTime+"没有要发送短信提醒的机构");
return;
}
//针对每个机构设置定时启动任务以及停止任务
InitializationTimer(currentTime, listSMSOrg);
}
/**
* 初始化每个机构的定时任务
* @param currentTime
* @param listSMSOrg
*/
public void InitializationTimer(String currentTime,List<Object[]> listSMSOrg) {
logger.info(currentTime+"根据省设置发送短信定时开始起止开始");
SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
for(Object[] org:listSMSOrg){
//获得每个省的机构 以及发送短信 起止时间
String orgCode = (String)org[0];
String orgDate = (String)org[1];
String orgStart = (String)org[2];
String orgEnd = (String)org[3];
Date dateStart = null;
Date dateEnd = null;
try {
dateStart = sdf.parse(orgDate+" "+orgStart+":00");
dateEnd = sdf.parse(orgDate+" "+orgEnd+":00");
} catch (ParseException e) {
e.printStackTrace();
logger.info(orgCode+currentTime+"发送短信日期异常,跳过发送 机构为"+orgCode +e);
continue;
}
// 需要创建 发送短信定时对象以及 停止发送短信定时对象,不能共用一个,因为 一个timer对象里的TimerTask会依次运行不会并行运行。
//创建发送短信定时器对象
Timer timerStart = new Timer();
TimerTask timerTaskStart= runTimes(currentTime,orgCode);
timerStart.schedule(timerTaskStart,dateStart);
//创建停止发送短信定时器对象
Timer timerEnd = new Timer();
TimerTask timerTaskEnd= endTimes(currentTime,orgCode,timerStart,timerEnd,timerTaskStart);
timerEnd.schedule(timerTaskEnd,dateEnd);
logger.info(currentTime+"定时起止发送短信设置成功 机构为"+orgCode+"开始时间为:"+dateStart+"结束时间为:"+dateEnd);
}
logger.info(currentTime+"根据省设置发送短信定时开始起止结束");
}
// 根据机构发送短信定时
public TimerTask runTimes(final String args, final String org) {
TimerTask task = new TimerTask() {
private boolean goOn = true;
long start = System.currentTimeMillis();
public void run() {
try {
logger.info(org+args+"发送短信定时开始机构为"+org);
//查询此机构下的短信开关是否开启
logger.info(org+args+"查询机构代码或其父级机构的短信场景编号为32的短信开关关闭数量"+org);
int smsClosedSwitchCount = 0;
smsClosedSwitchCount = overdueScoreService.selectSMSClosedSwitchCount(org);
if(smsClosedSwitchCount>0){/**短信开关有关闭状态**/
logger.info(org+args+":短信开关存在关闭状态,无法发送短信:"+org);
return;
}
/**短信模板**/
String smsModel="";
logger.info(org+args+"查询该机构或其父级机构的短信模板"+org);
smsModel=overdueScoreService.selectSMSModel(org);
if(StringUtils.isBlank(smsModel)){
logger.info(org+args+"未配置短信模板数据或短信模板内容为空"+smsModel);
return;
}
logger.info(org+args+"查询该机构或其父级机构的短信模板内容"+smsModel);
//发短信业务逻辑,并查询出会员的数据 发送短信
//需要发送的总条数
int memInfoCount=0;
memInfoCount = overdueScoreService.overdueScoreSMSCount(org);
logger.info(org+args+"查询该机构需要发送的总条数为"+memInfoCount);
if(memInfoCount==0){
logger.info(org+args+"无短信提醒数据"+org);
return;
}
//更新该机构为已经发送过短信
List<String> orgList = new ArrayList<String>();
orgList.add(org);
overdueScoreService.updatePushDate(orgList, args);
logger.info(org+args+"更新该机构的推送日期表推送日期为今天"+org);
//循环次数
int count=0;
final int selectCount=1;/**每次最多查询100条客户积分数据**/
//count=memInfoCount/selectCount + (memInfoCount%selectCount == 0 ? 0 : 1);
count =memInfoCount;
logger.info(org+args+"该机构分批发送次数为:"+count);
//一批数据一批数据的执行
for(int j=0;j<count;j++){
/**会员积分数据集合**/
List<Object[]> memInfoList=null;
memInfoList=overdueScoreService.overdueScoreSMSMemInfoList(org,selectCount,args);
if(memInfoList!=null && memInfoList.size()>0){
try {
overdueScoreService.overdueScoreSMSSend(memInfoList, smsModel, org,args);
} catch (Exception e) {
logger.error(org+args+"发送短信异常的机构为"+org+"次数为"+j, e);
j--;
continue;
}
}
//如果到时间还未发送完短信,则停止
while(!goOn){
long end = System.currentTimeMillis();
logger.info(org+args+"该机构在规定时间内短信未发送完"+org+",时间为:"+(end-start));
return;
}
//休息1秒
logger.info(org+args+"休眠1毫秒避免短信主键冲突");
Thread.sleep(1);
}
long end = System.currentTimeMillis();
logger.info(org+args+"该机构在规定时间内短信发送完"+org+",时间为:"+(end-start));
logger.info(org+args+"发送短信完成-----机构为"+org);
} catch (Exception e) {
logger.error(org+args+"发送短信异常的机构为"+org, e);
}
}
//重写了 cancel 方法 对私有变量goOn 赋值为false 目的停止正在运行的此方法
@Override
public boolean cancel() {
super.cancel();
return this.goOn = false;
}
};
return task;
}
//根据机构停止发送短信定时
public TimerTask endTimes(final String args, final String org,final Timer timerStart,final Timer timerEnd,final TimerTask timerTaskStart) {
TimerTask task = new TimerTask() {
public void run() {
timerTaskStart.cancel();
timerStart.cancel();
timerEnd.cancel();
logger.info(org+args+"发送短信定时结束机构为"+org);
}
};
return task;
}
}