2

I am attempting to create a scheduled job which runs every 5 minutes from 7 AM to 22 PM everyday. For example, it should runs at 7:00, 7:05, 7:10 ... 21:55, and then it should stop at 22:00. On the next day, it runs the same schedule again and so on.

I have found this example which shows how to use ScheduledExecutorService to start a task at particular time. How to run certain task every day at a particular time using ScheduledExecutorService?

I referred to the answer and write my code like below: (I am using Java 7)

class Scheduler {
    private ScheduledExecutorService executors;

    public static void main(String[] arg) {
       Runnable task = new Runnable() {
            @Override
            public void run() {
                ...DO SOMETHING...
            }
       };
        
       // Get how many seconds before the next start time (7AM).
       long initDelay = getInitialDelay(7); 
       
       ScheduledExecutorService executors = Executors.newSingleThreadScheduledExecutor();
       executors.scheduleAtFixedRate(task, initDelay, (60 * 5), TimeUnit.SECONDS);
   }

    private static long getInitialDelay(int hour) {
        Calendar calNow = Calendar.getInstance();

        Calendar cal = Calendar.getInstance();
        cal.set(Calendar.HOUR_OF_DAY, hour);
        cal.set(Calendar.MINUTE, 0);
        cal.set(Calendar.SECOND, 0);

        long diff = cal.getTimeInMillis() - calNow.getTimeInMillis();
        if (diff < 0) {
            cal.add(Calendar.DAY_OF_MONTH, 1);
            diff = cal.getTimeInMillis() - calNow.getTimeInMillis();
        }

        return diff / 1000;
    }
}

My above code starts at 7 AM and runs every 5 minutes perfectly. However, how can I do to control ScheduledExecuterService to stop the task at 22 PM and then start again at 7 AM on the next day?

Or, is there any better other way to run a task during particular period of time everyday?

theedchen
  • 1,564
  • 4
  • 10
  • 17
  • By the way, `Calendar` is a terrible class, and was supplanted years ago by th modern *java.time* classes with the adoption of JSR 310. For Java 6 and 7, see the *ThreeTen-Backport* project. – Basil Bourque Mar 28 '19 at 06:40

1 Answers1

1

A fixed scheduled executor service cannot alter its timing.

So use the single-run non-fixed scheduled executor service. Call ScheduledExecutorService::schedule. On its first run, check the current time. If before the end of the work day, call the same method schedule again, passing a delay of five minutes. If after the end of the work day, pass a delay of eight hours, the amount of time until the new work day starts.

So, a simple little trick. Each run of your runnable schedules the next run, endlessly.

Basil Bourque
  • 303,325
  • 100
  • 852
  • 1,154
  • Do you mean that I should create nested Executors ? – theedchen Mar 28 '19 at 07:08
  • @edyucheng Nope, just one `ScheduledExecutorService` object. And just one Runnable object. Your `Runnable` can call the `schedule` method to schedule its own next run. I may b able to write an example tomorrow, though some such Answers on Stack Overflow already show this. Or you can just think it through, as it is really quite simple. Check the time-of-day inside your `run` method. – Basil Bourque Mar 28 '19 at 08:04
  • After schedule the next run and the next-run is run, how to call the `schedule` method again ? I tried to used an infinite loop and put the `schedule` method inside, but it shows error.`while(true) { executor.schedule(task, 5, TimeUnit.MINUTE); }`. Could you show how to control and give an example ? Thank you so much ! – theedchen Mar 28 '19 at 08:42