Java利用TimerTask执行一次定时任务

209

​​携手创作,共同成长!这是我参与「掘金日新计划·8 月更文挑战」的第27天,点击查看活动详情

 

项目有个简单的小需求就是在考试时间结束后把待考的用户状态修改为缺考,可以利用TimerTask来实现,在java中实现定时执行任务的功能,主要用到Timer和TimerTask类。其中Timer是用来在一个后台线程按指定的计划来执行指定的任务。

在新增考试的时候添加一个定时任务:

// 添加执行任务(延迟 xxx秒执行,)

 timer.schedule(timerTask,(timestamp-(epochSecond*1000)));

public void performTimerTask(Long timestamp,Long id){

        long epochSecond = LocalDateTime.now().atZone(ZoneId.of("Asia/Shanghai")).toInstant().getEpochSecond();
        TimerTask timerTask = new TimerTask() {
            @Override
            public void run() {
                //获取参考人员记录列表,将待考修改为缺考
                List<ExamRecordVo> examRecordVos=examRecordBiz.getExamRecordList(id);
                for (int i = 0; i <examRecordVos.size() ; i++) {
                    //修改用户考试状态
                    ExamRecordVo recordVo = examRecordVos.get(i);
                    if(recordVo.getStatus()==ExamStatusEnum.WAIT.getCode()){//待考
                        ExamRecord examRecord =new ExamRecord();
                        examRecord.setId(recordVo.getRecordId());
                        examRecord.setStatus(ExamStatusEnum.ABSENT.getCode());//缺考
                        examRecordBiz.update(examRecord);
                    }
                }
            }
        };
        Timer timer = new Timer();
        timer.schedule(timerTask,(timestamp-(epochSecond*1000)));
    }

主要方法介绍:

public void schedule(TimerTask task, long delay)

该方法的含义是,表示定时器将延迟delay(毫秒)时间后,执行task任务。如果delay为负数或0,则任务会被立即进行。而且是一次性的执行任务,后续不会重复(或定时)执行该任务。

对于Timer类,还提供一个同样功能的方法,如下:

public void schedule(TimerTask task, Date time)

该方法与上面方法的区别是,上面方法是指定延期一段时间执行,这个方法是指定在某个具体的时间点执行。注意,如果系统的当前时间已经超过了参数time指定的时间,该任务会被立即执行。

由于传递给schedule方法的延迟参数的值为0,因此任务将立即执行。因此,两个语句的打印时间相同。经过研究,发现在创建定时器对象并执行timer timer=new timer()时;语句,创建定时器线程。即,即使上述代码没有定时器调度(任务,0);此语句,程序将不会退出。我认为这是很不合理的。再次研究定时器类的源代码后,发现它也有一个带布尔参数的构造函数:

public Timer(boolean isDaemon)

从参数名就可以看出,如果参数值为true时,则Timer创建的定时器线程为守护线程。守护线程的含义是,当java进程中所有的工作线程都退出后,守护线程就自动退出了。

定时器的退出

timer类提供了一个cancel方法来取消计时器。调用cancel方法将终止此计时器并放弃所有当前计划的任务。这不会干扰当前正在执行的任务(如果有)。一旦定时器终止,它的执行线程也将终止,并且不能根据它调度更多的任务。

请注意,通过在此计时器调用的计时器任务的run方法中调用此方法,您可以绝对确保正在执行的任务是此计时器执行的最后一个任务。此方法可以重复调用;但是第二次和随后的呼叫是无效的。