web-dev-qa-db-fra.com

Comment planifier une tâche à exécuter une fois?

Je veux retarder quelque chose, comme le réglage d’un compte à rebours qui "fera quelque chose" après un certain temps.

Je veux que le reste de mon programme continue à fonctionner pendant que j'attends, alors j'ai essayé de créer ma propre Thread qui contenait un délai d'une minute:

public class Scratch {
    private static boolean outOfTime = false;

    public static void main(String[] args) {
        Thread countdown = new Thread() {
            @Override
            public void run() {
                try {
                    // wait a while
                    System.out.println("Starting one-minute countdown now...");
                    Thread.sleep(60 * 1000);

                    // do the thing
                    outOfTime = true;
                    System.out.println("Out of time!");
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
            }
        };
        countdown.start();

        while (!outOfTime) {
            try {
                Thread.sleep(1000);
                System.out.println("do other stuff here");
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }
    }
}


.__ Bien que cela ait fonctionné plus ou moins, il semblait qu'il devrait y avoir une meilleure façon de le faire.

Après quelques recherches, j'ai trouvé un tas de questions comme celles-ci mais elles ne traitent pas vraiment de ce que j'essaie de faire:

Je n'ai besoin de rien d'aussi compliqué. Je veux juste faire une seule chose après un certain temps tout en laissant le reste du programme s'exécuter.

Comment devrais-je planifier une tâche ponctuelle pour "faire une chose"?

19
azurefrog

Alors que Java.util.Timer était un bon moyen de planifier des tâches futures, il est maintenant préférable1 d'utiliser à la place les classes du package Java.util.concurrent.

Il existe une ScheduledExecutorService spécialement conçue pour exécuter une commande après un délai (ou pour les exécuter périodiquement, mais cela ne concerne pas cette question).

Il a une méthode schedule(Runnable, long, TimeUnit) qui

Crée et exécute une action ponctuelle qui devient activée après le délai donné.


En utilisant une ScheduledExecutorService, vous pouvez ré-écrire votre programme comme ceci:

import Java.util.concurrent.*;

public class Scratch {
    private static final ScheduledExecutorService scheduler = Executors.newScheduledThreadPool(1);
    public static void main(String[] args) {
        System.out.println("Starting one-minute countdown now...");
        ScheduledFuture<?> countdown = scheduler.schedule(new Runnable() {
            @Override
            public void run() {
                // do the thing
                System.out.println("Out of time!");
            }}, 1, TimeUnit.MINUTES);

        while (!countdown.isDone()) {
            try {
                Thread.sleep(1000);
                System.out.println("do other stuff here");
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }
        scheduler.shutdown();
    }
}

Une des choses intéressantes que vous obtenez en faisant les choses de cette façon est l’objet ScheduledFuture<?> que vous obtenez en appelant schedule().

Cela vous permet de vous débarrasser de la variable supplémentaire boolean et de vérifier directement si le travail a été exécuté.

Vous pouvez également annuler la tâche planifiée si vous ne souhaitez plus attendre en appelant sa méthode cancel() .


1Voir Java Timer vs ExecutorService? pour éviter d'utiliser une Timer en faveur d'une ExecutorService.

25
azurefrog

Merci cela a fonctionné pour moi. J'ai utilisé le planificateur pour planifier une tâche à un batchinterval calculé au moment de l'exécution.

    manualTriggerBatchJob.setSchedulingProperties(pblId, batchInterval);
    ScheduledExecutorService scheduledExecutorService =
            Executors.newScheduledThreadPool(5);
    @SuppressWarnings("unchecked")
    ScheduledFuture scheduledFuture =
            scheduledExecutorService.schedule(manualTriggerBatchJob,
            batchIntervalInMin,TimeUnit.MILLISECONDS);
0
Apeksha Saxena