How to schedule a periodic task in Java?
Asked Answered
L

13

226

I need to schedule a task to run in at fixed interval of time. How can I do this with support of long intervals (for example on each 8 hours)?

I'm currently using java.util.Timer.scheduleAtFixedRate. Does java.util.Timer.scheduleAtFixedRate support long time intervals?

Lyso answered 18/10, 2011 at 21:38 Comment(0)
K
326

Use a ScheduledExecutorService:

 private final ScheduledExecutorService scheduler = Executors.newScheduledThreadPool(1);
 scheduler.scheduleAtFixedRate(yourRunnable, 8, 8, TimeUnit.HOURS);
Korikorie answered 18/10, 2011 at 21:44 Comment(1)
If you want this to run every day at a specific time there's not a great way to do it, because the TimeUnit applies to both the initialDelay and the period. Running every 24 hours will end up being thrown off when DST kicks in, but a TimeUnit of DAYS doesn't let you specify a fine-grained initialDelay. (I think the internal ScheduledExecutorService implementation converts DAYS to nanoseconds anyway).Upbuild
F
49

You should take a look to Quartz it's a java framework wich works with EE and SE editions and allows to define jobs to execute an specific time

Fascista answered 18/10, 2011 at 21:41 Comment(0)
C
31

Try this way ->

Firstly create a class TimeTask that runs your task, it looks like:

public class CustomTask extends TimerTask  {

   public CustomTask(){
 
     //Constructor

   }

   public void run() {
       try {
     
         // Your task process

       } catch (Exception ex) {
           System.out.println("error running thread " + ex.getMessage());
       }
    }
}

Then in main class you instantiate the task and run it periodically started by a precised date:

 public void runTask() {

        Calendar calendar = Calendar.getInstance();
        calendar.set(Calendar.DAY_OF_WEEK, Calendar.MONDAY);
        calendar.set(Calendar.HOUR_OF_DAY, 15);
        calendar.set(Calendar.MINUTE, 40);
        calendar.set(Calendar.SECOND, 0);
        calendar.set(Calendar.MILLISECOND, 0);


    
        Timer time = new Timer(); // Instantiate Timer Object

        // Start running the task on Monday at 15:40:00, period is set to 8 hours
        // if you want to run the task immediately, set the 2nd parameter to 0
        time.schedule(new CustomTask(), calendar.getTime(), TimeUnit.HOURS.toMillis(8));
}
Crutchfield answered 19/9, 2013 at 13:41 Comment(2)
To make the code more readable you could change the final argument in you schedule call to TimeUnit.HOURS.toMillis(8)Overspend
The documentation for Timer recommends using the Executor framework instead.Lahdidah
N
14

Use Google Guava AbstractScheduledService as given below:

public class ScheduledExecutor extends AbstractScheduledService {

   @Override
   protected void runOneIteration() throws Exception {
      System.out.println("Executing....");
   }

   @Override
   protected Scheduler scheduler() {
        return Scheduler.newFixedRateSchedule(0, 3, TimeUnit.SECONDS);
   }

   @Override
   protected void startUp() {
       System.out.println("StartUp Activity....");
   }


   @Override
   protected void shutDown() {
       System.out.println("Shutdown Activity...");
   }

   public static void main(String[] args) throws InterruptedException {
       ScheduledExecutor se = new ScheduledExecutor();
       se.startAsync();
       Thread.sleep(15000);
       se.stopAsync();
   }
}

If you have more services like this, then registering all services in ServiceManager will be good as all services can be started and stopped together. Read here for more on ServiceManager.

Nigro answered 21/7, 2014 at 16:5 Comment(0)
G
10

If you want to stick with java.util.Timer, you can use it to schedule at large time intervals. You simply pass in the period you are shooting for. Check the documentation here.

Gibbs answered 18/10, 2011 at 21:44 Comment(0)
L
9

Do something every one second

Timer timer = new Timer();
timer.schedule(new TimerTask() {
    @Override
    public void run() {
        //code
    }
}, 0, 1000);
Lifesaving answered 12/6, 2018 at 9:42 Comment(1)
The documentation for Timer recommends using the Executor framework insteadLahdidah
J
8

These two classes can work together to schedule a periodic task:

Scheduled Task

import java.util.TimerTask;
import java.util.Date;

// Create a class extending TimerTask
public class ScheduledTask extends TimerTask {
    Date now; 
    public void run() {
        // Write code here that you want to execute periodically.
        now = new Date();                      // initialize date
        System.out.println("Time is :" + now); // Display current time
    }
}

Run Scheduled Task

import java.util.Timer;

public class SchedulerMain {
    public static void main(String args[]) throws InterruptedException {
        Timer time = new Timer();               // Instantiate Timer Object
        ScheduledTask st = new ScheduledTask(); // Instantiate SheduledTask class
        time.schedule(st, 0, 1000);             // Create task repeating every 1 sec
        //for demo only.
        for (int i = 0; i <= 5; i++) {
            System.out.println("Execution in Main Thread...." + i);
            Thread.sleep(2000);
            if (i == 5) {
                System.out.println("Application Terminates");
                System.exit(0);
            }
        }
    }
}

Reference https://www.mkyong.com/java/how-to-run-a-task-periodically-in-java/

Jenifferjenilee answered 21/11, 2018 at 11:43 Comment(1)
Best solution until now, more clean and easy to implementKnurly
M
6

If your application is already using Spring framework, you have Scheduling built in

Mcintire answered 14/10, 2014 at 22:25 Comment(0)
R
5

I use Spring Framework's feature. (spring-context jar or maven dependency).

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.scheduling.annotation.Scheduled;
import org.springframework.stereotype.Component;


@Component
public class ScheduledTaskRunner {

    @Autowired
    @Qualifier("TempFilesCleanerExecution")
    private ScheduledTask tempDataCleanerExecution;

    @Scheduled(fixedDelay = TempFilesCleanerExecution.INTERVAL_TO_RUN_TMP_CLEAN_MS /* 1000 */)
    public void performCleanTempData() {
        tempDataCleanerExecution.execute();
    }

}

ScheduledTask is my own interface with my custom method execute, which I call as my scheduled task.

Riarial answered 21/7, 2016 at 11:28 Comment(0)
B
5

You can also use JobRunr, an easy to use and open-source Java Scheduler.

To schedule a Job every 8 hours using JobRunr, you would use the following code:

BackgroundJob.scheduleRecurrently(Duration.ofHours(8), () -> yourService.methodToRunEvery8Hours());

If you are using Spring Boot, Micronaut or Quarkus, you can also use the @Recurring annotation:


public class YourService {

    @Recurring(interval="PT8H")
    public void methodToRunEvery8Hours() {
        // your business logic
    }

}

JobRunr also comes with an embedded dashboard that allows you to follow-up on how your jobs are doing.

Bratton answered 13/2, 2023 at 11:45 Comment(1)
please note that the free version of JobRunr allows you to create only up to 100 recurring jobs.Trophoblast
R
3

Have you tried Spring Scheduler using annotations ?

@Scheduled(cron = "0 0 0/8 ? * * *")
public void scheduledMethodNoReturnValue(){
    //body can be another method call which returns some value.
}

you can do this with xml as well.

 <task:scheduled-tasks>
   <task:scheduled ref = "reference" method = "methodName" cron = "<cron expression here> -or- ${<cron expression from property files>}"
 <task:scheduled-tasks>
Retort answered 28/12, 2018 at 14:49 Comment(0)
B
0

my servlet contains this as a code how to keep this in scheduler if a user presses accept

if(bt.equals("accept")) {
    ScheduledExecutorService scheduler=Executors.newScheduledThreadPool(1);
    String lat=request.getParameter("latlocation");
    String lng=request.getParameter("lnglocation");
    requestingclass.updatelocation(lat,lng);
}
Babble answered 8/1, 2020 at 10:20 Comment(0)
P
-1

There is a ScheduledFuture class in java.util.concurrent, it may helps you.

Psychognosis answered 7/4, 2021 at 13:15 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.