Minuteur Java

Minuteur Java

1. Minuterie - Les bases

Timer etTimerTask sont des classes java util utilisées pour planifier des tâches dans un thread d'arrière-plan. En quelques mots -TimerTask is the task to perform and Timer is the scheduler.

2. Planifier une tâche une fois

Commençons simplement parrunning a single task à l’aide d’unTimer:

@Test
public void givenUsingTimer_whenSchedulingTaskOnce_thenCorrect() {
    TimerTask task = new TimerTask() {
        public void run() {
            System.out.println("Task performed on: " + new Date() + "n" +
              "Thread's name: " + Thread.currentThread().getName());
        }
    };
    Timer timer = new Timer("Timer");

    long delay = 1000L;
    timer.schedule(task, delay);
}

Notez que si nous exécutons ceci est un test JUnit, nous devons ajouter un appelThread.sleep(delay * 2) pour permettre au thread du Timer d'exécuter la tâche avant que le test Junit ne s'arrête.

3. Planifier une tâche répétée à un intervalle

Ensuite, nous allonsschedule a task to run at a pre-defined interval.

Nous utiliserons l'APIscheduleAtFixedRate(repeatedTask, delay, period), qui planifie la tâche pour une exécution répétée à taux fixe, en commençant après le délai spécifié. Les exécutions suivantes ont lieu à intervalles réguliers, séparés par la période spécifiée:

@Test
public void givenUsingTimer_whenSchedulingRepeatedTask_thenCorrect(){
    TimerTask repeatedTask = new TimerTask() {
        public void run() {
            System.out.println("Task performed on " + new Date());
        }
    };
    Timer timer = new Timer("Timer");

    long delay  = 1000L;
    long period = 1000L;
    timer.scheduleAtFixedRate(repeatedTask, delay, period);
}

Notez que - si une exécution est retardée pour une raison quelconque (telle qu'un nettoyage de la mémoire ou une autre activité en arrière-plan), deux exécutions ou plus se succèdent rapidement pour "rattraper".

3.1. Planifier une tâche quotidienne

Ensuite - disonsrun a task once a day:

@Test
public void givenUsingTimer_whenSchedulingDailyTask_thenCorrect() {
    TimerTask repeatedTask = new TimerTask() {
        public void run() {
            System.out.println("Task performed on " + new Date());
        }
    };
    Timer timer = new Timer("Timer");

    long delay = 1000L;
    long period = 1000L * 60L * 60L * 24L;
    timer.scheduleAtFixedRate(repeatedTask, delay, period);
}

4. AnnulerTimer etTimerTask

L'exécution d'une tâche peut être annulée de plusieurs manières:

4.1. Annuler lesTimerTask à l'intérieur desRun

En appelant la méthodeTimerTask.cancel() dans l’implémentation de la méthoderun() duTimerTask lui-même:

@Test
public void givenUsingTimer_whenCancelingTimerTask_thenCorrect()
  throws InterruptedException {
    TimerTask task = new TimerTask() {
        public void run() {
            System.out.println("Task performed on " + new Date());
            cancel();
        }
    };
    Timer timer = new Timer("Timer");

    timer.scheduleAtFixedRate(task, 1000L, 1000L);

    Thread.sleep(1000L * 2);
}

4.2. Annuler lesTimer

En appelant la méthodeTimer.cancel() sur un objetTimer:

@Test
public void givenUsingTimer_whenCancelingTimer_thenCorrect()
  throws InterruptedException {
    TimerTask task = new TimerTask() {
        public void run() {
            System.out.println("Task performed on " + new Date());
        }
    };
    Timer timer = new Timer("Timer");

    timer.scheduleAtFixedRate(task, 1000L, 1000L);

    Thread.sleep(1000L * 2);
    timer.cancel();
}

4.3. Arrêtez le fil desTimerTask à l'intérieur desRun

Vous pouvez également arrêter le thread dans la méthoderun de la tâche, annulant ainsi toute la tâche:

@Test
public void givenUsingTimer_whenStoppingThread_thenTimerTaskIsCancelled()
  throws InterruptedException {
    TimerTask task = new TimerTask() {
        public void run() {
            System.out.println("Task performed on " + new Date());
            // TODO: stop the thread here
        }
    };
    Timer timer = new Timer("Timer");

    timer.scheduleAtFixedRate(task, 1000L, 1000L);

    Thread.sleep(1000L * 2);
}

Notez l'instruction TODO dans l'implémentation derun - pour exécuter cet exemple simple, nous devons arrêter le thread.

Dans une implémentation de thread personnalisé dans le monde réel, l'arrêt du thread doit être pris en charge, mais dans ce cas, nous pouvons ignorer la dépréciation et utiliser l'API simplestop sur la classe Thread elle-même.

5. Timer VSExecutorService

Vous pouvez également utiliser un service d'exécution pour exécuter des tâches de minuterie, au lieu de l'utiliser.

Voici un exemple rapide de la façon d'exécuter une tâche répétée à un intervalle spécifié:

@Test
public void givenUsingExecutorService_whenSchedulingRepeatedTask_thenCorrect()
  throws InterruptedException {
    TimerTask repeatedTask = new TimerTask() {
        public void run() {
            System.out.println("Task performed on " + new Date());
        }
    };
    ScheduledExecutorService executor = Executors.newSingleThreadScheduledExecutor();
    long delay  = 1000L;
    long period = 1000L;
    executor.scheduleAtFixedRate(repeatedTask, delay, period, TimeUnit.MILLISECONDS);
    Thread.sleep(delay + period * 3);
    executor.shutdown();
}

Alors, quelles sont les principales différences entre la solutionTimer et la solutionExecutorService:

  • Timer peut être sensible aux changements d'horloge système; ScheduledThreadPoolExecutor n'est pas

  • Timer n'a qu'un seul thread d'exécution; ScheduledThreadPoolExecutor peut être configuré avec n'importe quel nombre de threads

  • Les exceptions d'exécution lancées à l'intérieur desTimerTask tuent le thread, donc les tâches planifiées suivantes ne s'exécuteront plus; avecScheduledThreadExecutor - la tâche en cours sera annulée, mais le reste continuera à s'exécuter

6. Conclusion

Ce didacticiel a illustré les nombreuses façons dont vous pouvez utiliser l'infrastructure simple mais flexible deTimer etTimerTask intégrée à Java, pour planifier rapidement les tâches. Il existe bien sûr des solutions beaucoup plus complexes et complètes dans le monde Java si vous en avez besoin - commethe Quartz library - mais c'est un très bon point de départ.

L'implémentation de ces exemples peut être trouvée dansthe github project - il s'agit d'un projet basé sur Eclipse, il devrait donc être facile à importer et à exécuter tel quel.