43

I want to execute a job everyday 2PM. Which method of java.util.Timer I can use to schedule my job?

After 2Hrs, run it will stop the job and reschedule for next day 2PM.

peterh
  • 11,875
  • 18
  • 85
  • 108
BOSS
  • 2,931
  • 8
  • 28
  • 53

9 Answers9

75
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
Roberto Milani
  • 760
  • 4
  • 20
  • 40
Daniel Gerber
  • 3,226
  • 3
  • 25
  • 32
  • 2
    vote up, but not accepted as the simplest answer tough, @Daniel Gerber? I wonder,.. – gumuruh Jul 15 '16 at 02:46
  • can't do anything about that :) – Daniel Gerber Jul 15 '16 at 09:08
  • the Timer class u r using is currently imported from java.util.Timer or javax.swing.Timer ? and what about if we want to execute the time at 2PM, would it be just typed as 14 for the Calendar.HOUR_OF_DAY values? @Daniel Gerber – gumuruh Jul 18 '16 at 08:52
  • 1
    This is a very, very bad idea as it does not meet the criteria that the timer job runs every day at the same time. Daylight savings and leap seconds will make this fail! – Zordid Aug 12 '20 at 14:30
23

You could use Timer.schedule(TimerTask task, Date firstTime, long period) method, setting firstTime to 2PM today and the setting the period to 24-hours:

Schedules the specified task for repeated fixed-delay execution, beginning at the specified time. Subsequent executions take place at approximately regular intervals, separated by the specified period.

hmjd
  • 120,187
  • 20
  • 207
  • 252
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();

    }

}
BOSS
  • 2,931
  • 8
  • 28
  • 53
5

The easiest way I've found of doing this has always been through Task Scheduler in Windows and cron in Linux.

However for Java, take a look at Quartz Scheduler

From their website:

Quartz is a full-featured, open source job scheduling service that can be integrated with, or used along side virtually any Java EE or Java SE application - from the smallest stand-alone application to the largest e-commerce system. Quartz can be used to create simple or complex schedules for executing tens, hundreds, or even tens-of-thousands of jobs; jobs whose tasks are defined as standard Java components that may execute virtually anything you may program them to do. The Quartz Scheduler includes many enterprise-class features, such as JTA transactions and clustering.

Ali
  • 12,354
  • 9
  • 54
  • 83
  • Take a look at this [schedule periodic tasks example](http://www.javapractices.com/topic/TopicAction.do?Id=54). Quartz is open source (Apache 2.0 License), technically you can just download the source and include it in your project. – Ali Feb 21 '12 at 10:36
  • 1
    @Ali, some government or banking company does not allow un-accepted 3rd party libraries inside the project... – Rudy Feb 21 '12 at 10:41
  • +1 since OS-level schedulers are the correct thing for tasks with that sort of timescale. – Donal Fellows Feb 21 '12 at 11:00
4

Most answers for this question and the following two questions assume that the milliseconds per day is always the same.
How to schedule a periodic task in Java?
How to run certain task every day at a particular time using ScheduledExecutorService?

However, it's not ture due to day lights saving and leap seconds. This means that if your service is alive for years and the accuracy of the timer matters, a fixed period timer is not your choice.

So, I'd like to introduce my code snippet for a more flexible timer than the 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;
}

Then, you can execute your job everyday 2PM by invoking the above method in the following way.

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

    // do your task...

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

The basic idea behind the code is to recalculate the left time to the next tick and start a new timer every time.

ThisaruG
  • 3,222
  • 7
  • 38
  • 60
Mr. Ree
  • 871
  • 9
  • 20
3

Why don't you use Spring's @Scheduled(cron="0 0 14 * * *") .. for sec, min, hours, day, month, dayOfWeek. V Cool. You can even specify 9-11 for 9:00 to 11:00, or MON-FRI in last parameter. You can invoke this programatically too, like is case of most of Spring, in case you want to set the time at runtime. See this:- http://docs.spring.io/spring/docs/current/spring-framework-reference/html/scheduling.html

Adding an example

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

        }
    }

also please annotate the class containing this with @Component annotation and please provide @EnableScheduling in the Application.java (class contains the main method) class to make spring aware that you are using taskscheduler in your applicaiton.

Arundev
  • 1,388
  • 23
  • 22
Apurva Singh
  • 4,534
  • 4
  • 33
  • 42
3

You should try using scheduleAtFixedRate (this will repeat your task). You will need to create an TimerTask object which will specify what to run (in run()) and when to run (scheduledExecutionTime). scheduleAtFixedRate also allows you to specify the first date of execution.

1

Due java.util.Timer:

Java 5.0 introduced the java.util.concurrent package and one of the concurrency utilities therein is the ScheduledThreadPoolExecutor which is a thread pool for repeatedly executing tasks at a given rate or delay. It is effectively a more versatile replacement for the Timer/TimerTask combination, as it allows multiple service threads, accepts various time units, and doesn't require subclassing TimerTask (just implement Runnable). Configuring ScheduledThreadPoolExecutor with one thread makes it equivalent to Timer.

so (add this code to your class):

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);

    }  
Alexey Simonov
  • 414
  • 4
  • 12
1

use public void schedule(TimerTask task,Date firstTime,long period)

to make the task repeats again the next day, just set period to 86400000 milliseconds ( which means 1 day )

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

Timer timer = new Timer();

timer.sc(myOwnTimerTask,date2pm, 86400000);
Rudy
  • 7,008
  • 12
  • 50
  • 85
  • @Ruby if my job run for 2hrs then the next schedule will be delayed by 2hrs? – BOSS Feb 21 '12 at 10:42
  • Yes. from Java Docs : In fixed-delay execution, each execution is scheduled relative to the actual execution time of the previous execution. If an execution is delayed for any reason (such as garbage collection or other background activity), subsequent executions will be delayed as well. In the long run, the frequency of execution will generally be slightly lower than the reciprocal of the specified period (assuming the system clock underlying Object.wait(long) is accurate). – Rudy Feb 21 '12 at 10:50
  • 3,600,000ms is an hour! – Daniel Gerber Aug 07 '13 at 07:06
  • change to 86400000 then. – Rudy Aug 07 '13 at 08:22