Comment planifier une tâche périodique en Java?

183

J'ai besoin de planifier une tâche à exécuter à intervalle de temps fixe. Comment puis-je faire cela avec le support de longs intervalles (par exemple toutes les 8 heures)?

J'utilise actuellement java.util.Timer.scheduleAtFixedRate. Supporte-t-il de java.util.Timer.scheduleAtFixedRatelongs intervalles de temps?

RYN
la source

Réponses:

261

Utilisez un ScheduledExecutorService :

 private final ScheduledExecutorService scheduler = Executors.newScheduledThreadPool(1);
 scheduler.scheduleAtFixedRate(yourRunnable, 8, 8, TimeUnit.HOURS);
b_erb
la source
1
Si vous voulez que cela s'exécute tous les jours à une heure précise, il n'y a pas de moyen idéal de le faire, car le TimeUnits'applique à la fois au initialDelayet au period. Exécution de toutes les 24 heures finir par être jeté quand l' heure d' été à coups de pied, mais TimeUnitde DAYSne vous permet pas de spécifier un grain fin initialDelay. (Je pense que l'implémentation interne ScheduledExecutorService se convertit DAYSde toute façon en nanosecondes).
Sam Barnum
46

Vous devriez jeter un oeil à Quartz c'est un framework java qui fonctionne avec les éditions EE et SE et permet de définir des jobs pour exécuter un temps spécifique

Jorge
la source
23

Essayez de cette façon ->

Commencez par créer une classe TimeTask qui exécute votre tâche, cela ressemble à:

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

puis dans la classe principale, vous instanciez la tâche et l'exécutez périodiquement à une date spécifiée:

 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));
}
Shessuky
la source
6
Pour rendre le code plus lisible, vous pouvez changer l'argument final dans votre appel planifié à TimeUnit.HOURS.toMillis (8)
darrenmc
La documentation de Timer recommande d'utiliser le framework Executor à la place.
Karan Khanna
14

Utilisez Google Guava AbstractScheduledServicecomme indiqué ci-dessous:

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

}

Si vous avez plus de services comme celui-ci, alors l'enregistrement de tous les services dans ServiceManager sera bon car tous les services peuvent être démarrés et arrêtés ensemble. Lisez ici pour en savoir plus sur ServiceManager.

Aride Chettali
la source
9

Si vous souhaitez vous en tenir java.util.Timer, vous pouvez l'utiliser pour planifier à de grands intervalles de temps. Vous passez simplement dans la période pour laquelle vous tirez. Consultez la documentation ici .

Belizzle
la source
5

Ces deux classes peuvent travailler ensemble pour planifier une tâche périodique:

Tâche planifiée

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
    }
}

Exécuter la tâche planifiée

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

Référence https://www.mkyong.com/java/how-to-run-a-task-periodically-in-java/

SumiSujith
la source
Meilleure solution jusqu'à présent, plus propre et facile à mettre en œuvre
Salvador Vigo
4

Faites quelque chose toutes les secondes

Timer timer = new Timer();
timer.schedule(new TimerTask() {
    @Override
    public void run() {
        //code
    }
}, 0, 1000);
Duchic
la source
1
La documentation de Timer recommande d'utiliser le framework Executor à la place
Karan Khanna
3

J'utilise la fonctionnalité de Spring Framework. ( jar de contexte de printemps ou dépendance maven).

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 est ma propre interface avec ma méthode personnalisée execute , que j'appelle comme tâche planifiée.

Yan Khonski
la source
2

Avez-vous essayé Spring Scheduler en utilisant des annotations?

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

vous pouvez également le faire avec xml.

 <task:scheduled-tasks>
   <task:scheduled ref = "reference" method = "methodName" cron = "<cron expression here> -or- ${<cron expression from property files>}"
 <task:scheduled-tasks>
madhu_karnati
la source
0

mon servlet contient ceci comme code comment le garder dans le planificateur si un utilisateur appuie sur accepter

if(bt.equals("accept")) {
    ScheduledExecutorService scheduler=Executors.newScheduledThreadPool(1);
    String lat=request.getParameter("latlocation");
    String lng=request.getParameter("lnglocation");
    requestingclass.updatelocation(lat,lng);
}
gopal krishna mareti
la source