web-dev-qa-db-fra.com

Comment supprimer une tâche de ScheduledExecutorService?

J'ai un ScheduledExecutorService qui exécute plusieurs tâches différentes périodiquement avec scheduleAtFixedRate(Runnable, INIT_DELAY, ACTION_DELAY, TimeUnit.SECONDS);

J'ai aussi une Runnable différente que j'utilise avec ce planificateur . Le problème commence lorsque je veux supprimer l'une des tâches du planificateur.

Y a-t-il un moyen de faire cela?

Est-ce que je fais la bonne chose en utilisant un planificateur pour différentes tâches? Quel est le meilleur moyen de mettre cela en œuvre?

52
thepoosh

Annulez simplement le futur retourné par scheduledAtFixedRate():

// Create the scheduler
ScheduledExecutorService scheduledExecutorService = Executors.newScheduledThreadPool(1);
// Create the task to execute
Runnable r = new Runnable() {
    @Override
    public void run() {
        System.out.println("Hello");
    }
};
// Schedule the task such that it will be executed every second
ScheduledFuture<?> scheduledFuture =
    scheduledExecutorService.scheduleAtFixedRate(r, 1L, 1L, TimeUnit.SECONDS);
// Wait 5 seconds
Thread.sleep(5000L);
// Cancel the task
scheduledFuture.cancel(false);

Une autre chose à noter est que annuler ne supprime pas la tâche du planificateur. Tout ce que cela garantit est que la méthode isDone renvoie toujours true. Cela peut entraîner des fuites de mémoire si vous continuez à ajouter de telles tâches. Par exemple, si vous démarrez une tâche en fonction d'une activité client ou d'un clic sur le bouton de l'interface utilisateur, répétez-la n fois et quittez-la. Si ce bouton est cliqué trop de fois, vous risquez de vous retrouver avec un grand pool de threads qui ne peuvent pas être nettoyés, car le planificateur a toujours une référence.

Vous voudrez peut-être utiliser setRemoveOnCancelPolicy(true) dans la classe ScheduledThreadPoolExecutor disponible à partir de Java 7. Pour la compatibilité ascendante, la valeur par défaut est false.

75
JB Nizet

Si votre instance ScheduledExecutorService s'étend ThreadPoolExecutor (par exemple, ScheduledThreadPoolExecutor), vous pouvez utiliser remove(Runnable) (mais consultez la note dans son javadoc: "Il peut échouer à supprimer des tâches converties en d'autres formulaires avant d'être placées dans la file d'attente interne.") Ou purge() .

0
Gary