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

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

好了,不多说 上代码:这里数据是存的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 + "]";
    }
}

原文地址:https://www.cnblogs.com/erlongxizhu-03/p/11211250.html

时间: 2024-10-16 06:41:31

定时任务,客户页面操作,使用java.util.timer(要求时间精确度不高的定时任务)的相关文章

java.util.Timer类似于闹钟定时做任务

在web中实现任务计划,相当于实现闹钟的功能,要完成2个步骤: 1.定时器的设置: 2.对这个定时器的启动运行和停止进行实时监听 java.util.Timer定时器,实际上是个线程,定时调度所拥有的TimerTasks 一个TimerTask实际上就是一个拥有run方法的类,需要定时执行的代码放到run方法体内,TimerTask一般是以匿名类方式创建. Timer是一种线程设施,用于安排以后在后台线程执行的任务,可安排任务执行一次,或者定期重复执行,可以看成一个定时器,可调度TimerTas

细说java.util.Timer

Timer是用于管理在后台执行的延迟任务或周期性任务,其中的任务使用java.util.TimerTask表示.任务的执行方式有两种: 按固定速率执行:即scheduleAtFixedRate的两个重载方法 按固定延迟执行:即schedule的4个重载方法 具体差别会在后面详细说明. 我们要实现一个定时任务,只需要实现TimerTask的run方法即可.每一个任务都有下一次执行时间nextExecutionTime(毫秒),如果是周期性的任务,那么每次执行都会更新这个时间为下一次的执行时间,当n

java.util.Timer简介

Timer是用于管理在后台执行的延迟任务或周期性任务,其中的任务使用java.util.TimerTask表示.任务的执行方式有两种: 按固定速率执行:即scheduleAtFixedRate的两个重载方法按固定延迟执行:即schedule的4个重载方法具体差别会在后面详细说明. 我们要实现一个定时任务,只需要实现TimerTask的run方法即可.每一个任务都有下一次执行时间nextExecutionTime(毫秒),如果是周期性的任务,那么每次执行都会更新这个时间为下一次的执行时间,当nex

SpringMvc中Hashmap操作遇到 java.util.ConcurrentModificationException: null

代码按照网上修改为类似,还不能解决问题 for (Iterator<String> it = target.keySet().iterator(); it.hasNext(); ) { if(...) it.remove(); } ,后来根据异常名称,推测是在Servlet多线程环境下保持,换成并发ConcurrentHashMap就解决问题了. 参考: HashMap报错:java.util.ConcurrentModificationException 原文地址:https://www.c

MongoDB的CRUD操作(java Util )

1.保存插入操作: public static synchronized String insert(DBObject record) { DBCollection col = MongoDB.getDBCollection(TABLE_NAME); record.put("time", new Date().getTime()); WriteResult result = col.insert(record); //当前插入表的_id return record.get("

定时任务:Java中Timer和TimerTask的使用

java.util.Timer定时器,实际上是个线程,定时调度所拥有的TimerTasks. 一个TimerTask实际上就是一个拥有run方法的类,需要定时执行的代码放到run方法体内,TimerTask一般是以匿名类的方式创建. 一个完整的Timer: Java代码   java.util.Timer timer = new java.util.Timer(true); // true 说明这个timer以daemon方式运行(优先级低, // 程序结束timer也自动结束),注意,java

JAVA之Timer定时器

1.原理 JDK中,定时器任务的执行需要两个基本的类:java.util.Timer;java.util.TimerTask; java.util.Timer定时器,实际上是个线程,定时调度所拥有的TimerTasks.一个TimerTask实际上就是一个拥有run方法的类,需要定时执行的代码放到run方法体内,TimerTask一般是以匿名类的方式创建. 要运行一个定时任务,最基本的步骤如下:1.建立一个要执行的任务TimerTask.2.创建一个Timer实例,通过Timer提供的sched

Java中Timer的用法--转载之网络

用法很简单,new一个timer,然后写一个timertask的子类即可. import java.util.Timer; import java.util.TimerTask; public class M { public static void main(String[] args) { // TODO todo.generated by zoer Timer timer = new Timer(); timer.schedule(new MyTask(), 1000, 2000); }

Java中Timer的用法

现在项目中用到需要定时去检查文件是否更新的功能.timer正好用于此处. 用法很简单,new一个timer,然后写一个timertask的子类即可. 代码如下: package comz.autoupdatefile; import java.util.Timer; import java.util.TimerTask; public class M { public static void main(String[] args) { // TODO todo.generated by zoer