我如何每天下午2点运行我的TimerTask

时间:2012-02-21 10:27:01

标签: java timer scheduled-tasks

我想每天下午2点执行一份工作。 java.util.Timer我可以使用哪种方法安排工作?

2小时后,它将停止工作,并在下午2点重新安排工作。

9 个答案:

答案 0 :(得分:54)

Calendar today = Calendar.getInstance();
today.set(Calendar.HOUR_OF_DAY, 2);
today.set(Calendar.MINUTE, 0);
today.set(Calendar.SECOND, 0);

// every night at 2am you run your task
Timer timer = new Timer();
timer.schedule(new YourTask(), today.getTime(), TimeUnit.MILLISECONDS.convert(1, TimeUnit.DAYS)); // period: 1 day

答案 1 :(得分:22)

您可以使用Timer.schedule(TimerTask task, Date firstTime, long period)方法,将firstTime设置为今天下午2点,将period设置为24小时:

  

从指定时间开始,为重复的固定延迟执行计划指定的任务。随后的执行大约定期进行,以指定的时间段分开。

答案 2 :(得分:15)

import java.util.Calendar;
import java.util.Date;
import java.util.GregorianCalendar;
import java.util.Timer;
import java.util.TimerTask;


public class MyTimerTask extends TimerTask {
    private final static long ONCE_PER_DAY = 1000*60*60*24;

    //private final static int ONE_DAY = 1;
    private final static int TWO_AM = 2;
    private final static int ZERO_MINUTES = 0;


    @Override
    public void run() {
        long currennTime = System.currentTimeMillis();
        long stopTime = currennTime + 2000;//provide the 2hrs time it should execute 1000*60*60*2
          while(stopTime != System.currentTimeMillis()){
              // Do your Job Here
            System.out.println("Start Job"+stopTime);
            System.out.println("End Job"+System.currentTimeMillis());
          }
    }
    private static Date getTomorrowMorning2AM(){

        Date date2am = new java.util.Date(); 
           date2am.setHours(TWO_AM); 
           date2am.setMinutes(ZERO_MINUTES); 

           return date2am;
      }
    //call this method from your servlet init method
    public static void startTask(){
        MyTimerTask task = new MyTimerTask();
        Timer timer = new Timer();  
        timer.schedule(task,getTomorrowMorning2AM(),1000*10);// for your case u need to give 1000*60*60*24
    }
    public static void main(String args[]){
        startTask();

    }

}

答案 3 :(得分:4)

我发现这样做的最简单方法一直是通过Windows中的Task Scheduler和Linux中的cron。

但是对于Java,请查看Quartz Scheduler

从他们的网站:

  

Quartz是一个功能齐全的开源作业调度服务   与几乎任何Java EE或Java集成或一起使用   SE应用程序 - 从最小的独立应用程序到   最大的电子商务系统。 Quartz可用于创建简单或   执行数十,数百甚至甚至的复杂计划   成千上万的工作;任务被定义为标准的作业   Java组件,可以执行您可能编程的几乎任何内容   他们这样做。 Quartz Scheduler包含许多企业级   功能,例如JTA事务和群集。

答案 4 :(得分:3)

您应该尝试使用scheduleAtFixedRate(这将重复您的任务)。您将需要创建一个TimerTask对象,该对象将指定要运行的内容(在run()中)和何时运行(scheduledExecutionTime)。 scheduleAtFixedRate还允许您指定第一个执行日期。

答案 5 :(得分:2)

为什么不使用Spring的@Scheduled(cron =" 0 0 14 * * *")..秒,分钟,小时,日,月,日我们周。 V酷。您甚至可以在9:00到11:00指定9-11,或在最后一个参数指定MON-FRI。 您也可以以编程方式调用此方法,就像大多数Spring的情况一样,以防您想在运行时设置时间。 看到这个: - http://docs.spring.io/spring/docs/current/spring-framework-reference/html/scheduling.html

添加示例

   @Scheduled(cron="0 0 14 * * *")
    public void customScheduler(){
        try{
            // do what ever you want to run repeatedly
        }catch(Exception e){
            e.printStackTrace();

        }
    }

还请使用@Component注释注释包含此类的类,并在Application.java(类包含main方法)类中提供@EnableScheduling,以使spring意识到您在应用程序中使用了taskscheduler。

答案 6 :(得分:1)

使用public void schedule(TimerTask任务,Date firstTime,long period)

使第二天再次重复任务,只需将时间段设置为86400000毫秒(即1天)

Date date2pm = new java.util.Date();
date2pm.setHour(14);
date2pm.setMinutes(0);

Timer timer = new Timer();

timer.sc(myOwnTimerTask,date2pm, 86400000);

答案 7 :(得分:1)

java.util.Timer到期:

  

Java 5.0引入了java.util.concurrent软件包,其中之一是   其中的并发实用程序是ScheduledThreadPoolExecutor   是用于以给定速率重复执行任务的线程池,或者   延迟。实际上,它是多功能的替代品   Timer / TimerTask组合,因为它允许多个服务线程,   接受各种时间单位,不需要子类化TimerTask   (只需实现Runnable)。配置ScheduledThreadPoolExecutor   一个线程使它等效于Timer。

所以(将此代码添加到您的班级中):

private ScheduledExecutorService scheduledExecutorService;

    public ScheduledSendLog() {
        init();
    }

    public void destroy() {
        this.scheduledExecutorService.shutdown();
    }

    private void init() {
        scheduledExecutorService =
                Executors.newScheduledThreadPool(1);
        System.out.println("---ScheduledSendLog created " + LocalDateTime.now());
        startSchedule(LocalTime.of(02, 00));
    }


    private void startSchedule(LocalTime atTime) {
        this.scheduledExecutorService.scheduleWithFixedDelay(() -> {
                    System.out.println(Thread.currentThread().getName() +
                            " |  scheduleWithFixedDelay | " + LocalDateTime.now());
                    // or whatever you want
                }, calculateInitialDelayInSec(atTime),
                LocalTime.MAX.toSecondOfDay(),
                TimeUnit.SECONDS);
    }

    private long calculateInitialDelayInSec(LocalTime atTime) {
        int currSec = LocalTime.now().toSecondOfDay();
        int atSec = atTime.toSecondOfDay();
        return (currSec < atSec) ?
                atSec - currSec : (LocalTime.MAX.toSecondOfDay() + atSec - currSec);

    }  

答案 8 :(得分:1)

此问题和以下两个问题的大多数答案假设每天的毫秒数始终相同
How to schedule a periodic task in Java?
How to run certain task every day at a particular time using ScheduledExecutorService?

但是,由于节省日光和leap秒,因此无法实现。 这意味着,如果您的服务可以使用多年,并且计时器的准确性至关重要, 固定时间计时器不是您的选择。

因此,我想介绍我的代码段,以提供比java.util.Timer更灵活的计时器。

package szx;

import java.time.LocalDateTime;
import java.time.ZoneId;
import java.util.Date;
import java.util.Timer;
import java.util.TimerTask;
import java.util.function.Function;

public class ScheduledExecutor {
    public void scheduleRegularly(Runnable task, LocalDateTime firstTime,
            Function<LocalDateTime, LocalDateTime> nextTime) {
        pendingTask = task;
        scheduleRegularly(firstTime, nextTime);
    }

    protected void scheduleRegularly(LocalDateTime firstTime,
            Function<LocalDateTime, LocalDateTime> nextTime) {
        new Timer().schedule(new TimerTask() {
            @Override
            public void run() {
                scheduleRegularly(nextTime.apply(firstTime), nextTime);
                pendingTask.run();
            }
        }, Date.from(firstTime.atZone(ZoneId.systemDefault()).toInstant()));
    }

    private volatile Runnable pendingTask = null;
}

然后,您可以通过以下方式调用上述方法来每天下午2点执行工作。

new ScheduledExecutor().scheduleRegularly(() -> {

    // do your task...

}, LocalDateTime.now().truncatedTo(ChronoUnit.DAYS).withHour(14), thisTime -> thisTime.plusDays(1));

代码的基本思想是重新计算到下一个刻度的剩余时间,并每次都启动一个新计时器。