Search code examples
javafor-loopscheduledexecutorservice

SingleThreadScheduledExecutor running schedule


I have a run method that contains a singleThreadScheduledExecutor. The goal is to have this run every 30 minutes during the day between 6 am and 8 pm. If the day is on the weekend or outside of those hours, the runtime program should add a message to the log and wait to try again in another 30 minutes.

However when the server starts my program and it is within the correct time range, (in this case let's say it tries to run the program for the first time at 7 am) when it goes past the appointed time it will still run (in this case it tries again at 830 pm but will still run). Debugging through it goes through the if statements and simply ignores the case. I have also found that if I run my program outside of the correct hours it will add an error message to the log as it should, but when it goes back to within the correct time frame it will continue to just log errors instead of running the program.

My question is thus: is there something I missed within the logic that I simply am not seeing? Is there a better/more efficient way to do this?

Thanks in advance.

Attached below is the code

public final void run() {
    final Calendar cal = Calendar.getInstance();
    exec = Executors.newSingleThreadScheduledExecutor();
    exec.scheduleAtFixedRate(new Runnable() {
        public void run() {
            try {

                if (cal.get(Calendar.DAY_OF_WEEK) == 1 || cal.get(Calendar.DAY_OF_WEEK) == 7) {
                    Globals.addMessage("Non-scheduled work day, please try again later.");
                    Globals.addMessage("Process aborted.");
                    running = false;

                }
                else if (cal.get(Calendar.HOUR_OF_DAY) < 6 || cal.get(Calendar.HOUR_OF_DAY) > 20) {
                    Globals.addMessage("Non-scheduled work hours, please try again later.");
                    Globals.addMessage("Process aborted.");
                    running = false;

                }
                else {
                    running = true;
                    Runtime rt = Runtime.getRuntime();
                    rt.exec(ServerVar.getVariable(ServerVars.PATH));
                    Globals.addMessage("Program is running.");
                }
            }
            catch (IOException e) {
                Globals.addMessage(e.toString());

            }

        }
    }

        , 0, 30, TimeUnit.MINUTES);
}

Solution

  • You're always using the same Calendar. Try this:

    public final void run() {
        exec = Executors.newSingleThreadScheduledExecutor();
        exec.scheduleAtFixedRate(new Runnable() {
            public void run() {
                final Calendar cal = Calendar.getInstance();
                try {
    
                    if (cal.get(Calendar.DAY_OF_WEEK) == 1 || cal.get(Calendar.DAY_OF_WEEK) == 7) {
                        Globals.addMessage("Non-scheduled work day, please try again later.");
                        Globals.addMessage("Process aborted.");
                        running = false;
    
                    }
                    else if (cal.get(Calendar.HOUR_OF_DAY) < 6 || cal.get(Calendar.HOUR_OF_DAY) > 20) {
                        Globals.addMessage("Non-scheduled work hours, please try again later.");
                        Globals.addMessage("Process aborted.");
                        running = false;
    
                    }
                    else {
                        running = true;
                        Runtime rt = Runtime.getRuntime();
                        rt.exec(ServerVar.getVariable(ServerVars.PATH));
                        Globals.addMessage("Program is running.");
                    }
                }
                catch (IOException e) {
                    Globals.addMessage(e.toString());
    
                }
    
            }
        }
    
            , 0, 30, TimeUnit.MINUTES);
    }