zoukankan      html  css  js  c++  java
  • 定时任务,客户页面操作,使用java.util.timer(要求时间精确度不高的定时任务)

    1. 定时任务,客户页面操作,使用java.util.timer,因为@schedule 注解中定时的时间不能在不启动项目情况下修改。
    2. timer.cancel()任务队列全部移除,task.cancel()只移除队列中的一个任务。
    3. 页面操作定时任务,传递参数(访问任务接口URL和对应参数),修改timer 中Task,修改需要先移除Task.cancel()。
    4. 注意timer只能有一个对象,因为多个就会造成多线程定时任务(多线程需要保证每个队列timer中任务不重复)。

    如果定时任务要求分布式请使用quartz

    好了,不多说 上代码:这里数据是存的Redis。

        //线程安全map:ConcurrentHashMap
        private Map<String, AutoEvalTask> timerTaskMap ;//<userName+taskName,timerTask>
        private Timer timer ;//不能放到方法里边,new 一个启动一个线程//启动了一个新线程,这个新线程并不是守护线程,所以会一直运行
        public Timer getTimer() {
            return timer;
        }
        public void setTimer(Timer timer) {
            this.timer = timer;
        }
        //AutoEvalTask task = new AutoEvalTask();//不能放到方法里边,
        
        /**
         * 启动所有定时任务
         * @param firstTimeStr
         * @param periodStr 秒数
         * @return
         */
        @RequestMapping(value="/lanchAllTimerTask")
        @ResponseBody
        public Map<String, String> lanchAllTimerTask() {
            Map<String, String> res = new HashMap<String, String>();
            try {
                Map<Object, Object> hmget = redisUtil.hmget("seller_schedule_time_list");
                for (Entry<Object, Object> map : hmget.entrySet()) {
                    String key = (String) map.getKey();//username+taskName
                    UserScheduleTimes value = (UserScheduleTimes) map.getValue();//定时任务信息对象
                    if (CollectionUtils.isEmpty(timerTaskMap)) {
                        timerTaskMap = new ConcurrentHashMap<String, AutoEvalTask>();
                    }
                    AutoEvalTask task = timerTaskMap.get(key);
                    if (task!=null) {
                        task.cancel();//从定时任务队列中移除
                    }
                    if (timer==null) {
                        timer = new Timer();//只有一个此定时任务队列。
                    }
                    task = new AutoEvalTask();//定时任务对象
                    //task = SpringContextHolder.getBean("autoEvalTask");//会报异常 java.lang.IllegalStateException: Task already scheduled or cancelled
                    task.setUserScheduleTimes(value);
                    timerTaskMap.put(key, task);
                    if (value !=null) {
                        Date HHmmDate = value.getFirstTime();
                        Date executeDate = getExecuteDate(HHmmDate);
                        timer.schedule(task, executeDate, value.getPeriod()*1000);//如果时间在当前时间之前,立即执行。然后间隔时间再次执行。
                    }
                    LOGGER.info("key:"+key+",value:"+value);
                }
                res.put("status", "succ");
            } catch (Exception e) {
                LOGGER.info("lanchAllTimerTask方法异常!",e);
                e.printStackTrace();
                res.put("status", "fail");
            }
            return res;
        }
        /**
         * 获取执行定时任务时刻,如果是当前时刻之前 第二天此时刻开始执行
         * @param HHmmDate
         * @return
         */
        private Date getExecuteDate(Date HHmmDate) {
            Calendar now = Calendar.getInstance();
            Date executeDate = new Date(now.get(Calendar.YEAR) - 1900, now.get(Calendar.MONTH), 
                    now.get(Calendar.DAY_OF_MONTH), HHmmDate.getHours(), HHmmDate.getMinutes(), HHmmDate.getSeconds());
            if (executeDate.compareTo(new Date())<0) {//不加此设置,如果是当前时刻 立即执行
                executeDate = DatesUtils.getTimePeriodBeforeDate(-1, executeDate);//1天后的此时刻执行任务。(最准确是开始时间+间隔倍数 大于当前时间最近的时间)
            }
            return executeDate;
        }
    /**
     * 定时任务类
    * @author zel 
    * @date 2019年7月22日 下午8:44:35 
    *
     */
    @Component
    public class AutoEvalTask extends TimerTask{
        private static final Logger LOGGER = LoggerFactory.getLogger(AutoEvalTask.class);
        //@Autowired
        AutoEvaluateTask autoEvaluateTask = SpringContextHolder.getBean("autoEvaluateTask");//外边AutoEvalTask是new的则不会注入
        private UserScheduleTimes userScheduleTimes;
        
        public UserScheduleTimes getUserScheduleTimes() {
            return userScheduleTimes;
        }
    
        public void setUserScheduleTimes(UserScheduleTimes userScheduleTimes) {
            this.userScheduleTimes = userScheduleTimes;
        }
    
        /* (non-Javadoc)
         * @see java.util.TimerTask#run()
         */
        @Override
        public void run() {
            try {
                //String url = "http://192.168.1.10:30002/tradeserver/delaysendmsg.api/scheduleTask/autoEvaluateInterface";
                String url = this.userScheduleTimes.getUrl();
                Map<String, String> param = this.userScheduleTimes.getParam();
                String userName = param.get("userName");
                if (userName.indexOf(",")!=-1) {
                    String[] split = userName.split(",");
                    for (int i = 0; i < split.length; i++) {
                        LOGGER.info(split[i] + ",多个用户测试定时任务");
                        //autoEvaluateTask.autoEvaluateAllFinished2(split[i], "35");
                        Map<String, String> paramInterfaceUrl = new HashMap<String, String>();
                        paramInterfaceUrl.put("userName", split[i]);
                        String httpGetWithJSON = HttpClientUtil.httpGetWithJSON(url, paramInterfaceUrl);
                        LOGGER.info("定时任务"+this.userScheduleTimes.getTaskName()+"结果:"+httpGetWithJSON);
                    }
                } else {//单个用户
                    LOGGER.info(userName + ",单个测试定时任务");
                    //autoEvaluateTask.autoEvaluateAllFinished2(userName, "35");
                    String httpGetWithJSON = HttpClientUtil.httpGetWithJSON(url, param);
                    LOGGER.info("定时任务"+this.userScheduleTimes.getTaskName()+"结果:"+httpGetWithJSON);
                }
            } catch (Exception e) {
                e.printStackTrace();
                LOGGER.info("定时任务run方法异常!",e);
            }
        }

    相关实体类entity:

    /** 
     * 客户设置的定时任务 时间点和 间隔时长,
    * @author zel 
    * @date 2019年7月19日 下午12:16:51 
    *  
    */
    public class UserScheduleTimes implements Serializable{
        
        /**
         * 
         */
        private static final long serialVersionUID = 8534961773338501488L;
        private String taskName;//定时任务名称
        //url 及参数信息:
        private String url;//定时执行URL,并附带参数。
        private Map<String, String> param;//参数,transient:不被序列化
    //    private String userName;//多用户逗号隔开
    //    private String orderTime;//订单时间
    //    private String type;//"manyUser":多用户 。
        //任务参数
        private Date firstTime;//任务开始执行时间。
        private Long period;//任务间隔时长 单位/秒
        
        
        public Map<String, String> getParam() {
            return param;
        }
        public void setParam(Map<String, String> param) {
            this.param = param;
        }
        public String getUrl() {
            return url;
        }
        public void setUrl(String url) {
            this.url = url;
        }
        public String getTaskName() {
            return taskName;
        }
        public void setTaskName(String taskName) {
            this.taskName = taskName;
        }
        public Date getFirstTime() {
            return firstTime;
        }
        public void setFirstTime(Date firstTime) {
            this.firstTime = firstTime;
        }
        public Long getPeriod() {
            return period;
        }
        public void setPeriod(Long period) {
            this.period = period;
        }
        @Override
        public String toString() {
            return "UserScheduleTimes [taskName=" + taskName + ", url=" + url + ", param=" + param + ", firstTime=" + firstTime + ", period=" + period + "]";
        }
    }
    源码,是痛苦的,又是快乐的,如果没有这痛苦,也就没有了这快乐!
  • 相关阅读:
    tp5的 LayUI分页样式实现
    BSBuDeJie_05
    WCF 程序入门
    iOS Xcode 调试技巧
    Visual Studio 2015 如何将全英界面转成中文
    BSBuDeJie_04
    BSBuDeJie_03
    BSBuDeJie_02
    BSBuDeJie_01
    iOS 一些琐碎的知识点
  • 原文地址:https://www.cnblogs.com/erlongxizhu-03/p/11211250.html
Copyright © 2011-2022 走看看