使用Timer实现定时启动 并定时停止

使用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;
    }
}

猜你喜欢

转载自blog.csdn.net/Aseasonv/article/details/81382375