定时任务,客户页面操作,使用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 + "]";
    }
}

 

posted @ 2019-07-31 10:09  好Wu赖  阅读(444)  评论(0编辑  收藏  举报