Question

J'ai un code dans lequel je planifie une tâche à l'aide de java.util.timer . Je regardais autour de moi et j'ai vu que ExecutorService pouvait faire la même chose. Donc, cette question ici, avez-vous utilisé Timer et ExecutorService pour planifier des tâches, quel est l'avantage d'une utilisation par rapport à une autre?

Voulait également vérifier si quelqu'un avait utilisé la classe Timer et rencontré des problèmes que le ExecutorService avait résolus pour eux.

Était-ce utile?

La solution

Selon la concurrence de Java en pratique :

  • Timer peut être sensible aux modifications de l'horloge système. ScheduledThreadPoolExecutor ne l'est pas.
  • Timer n'a qu'un seul thread d'exécution. Par conséquent, une tâche de longue durée peut retarder d'autres tâches. ScheduledThreadPoolExecutor peut être configuré avec un nombre quelconque de threads. De plus, vous avez un contrôle total sur les threads créés, si vous le souhaitez (en fournissant ThreadFactory ).
  • Les exceptions d'exécution levées dans TimerTask tuent ce thread, rendant ainsi Timer mort :-( ... c'est-à-dire que les tâches planifiées ne s'exécutent plus. ScheduledThreadExecutor non seulement attrape les exceptions d'exécution, mais vous permet de les gérer si vous le souhaitez (en remplaçant la méthode afterExecute à partir de ThreadPoolExecutor ). La tâche qui a lancé l'exception sera annulée, d'autres tâches continueront à s'exécuter.

Si vous pouvez utiliser ScheduledThreadExecutor au lieu de Minuteur , faites-le.

Encore une chose ... Bien que ScheduledThreadExecutor ne soit pas disponible dans la bibliothèque Java 1.4, il existe un Backport de JSR 166 ( java.util.concurrent ) vers Java 1.2, 1.3, 1.4 , qui possède la classe ScheduledThreadExecutor .

Autres conseils

S'il est disponible, il est difficile de trouver une raison de ne pas utiliser le framework d'exécution Java 5. Appel:

ScheduledExecutorService ex = Executors.newSingleThreadScheduledExecutor();

vous donnera un ScheduledExecutorService avec des fonctionnalités similaires à Timer (c’est-à-dire qu’il sera mono-threaded) mais dont l’accès peut être légèrement plus évolutif (sous le capot, il utilise des structures concurrentes plutôt qu'une synchronisation complète comme avec la classe Timer . L'utilisation d'un ScheduledExecutorService vous offre également des avantages tels que:

  • Vous pouvez le personnaliser si nécessaire (voir la classe newScheduledThreadPoolExecutor () ou la ScheduledThreadPoolExecutor
  • Les exécutions uniques peuvent renvoyer des résultats

Les seules raisons pour lesquelles je reste fidèle à Minuteur sont les suivantes:

  • Il est disponible avant Java 5
  • Une classe similaire est fournie dans J2ME, ce qui pourrait faciliter le portage de votre application (mais il ne serait pas très difficile d'ajouter une couche d'abstraction commune dans ce cas)

ExecutorService est plus récent et plus général. Une minuterie est juste un fil qui exécute périodiquement les choses que vous avez programmées pour cela.

Un ExecutorService peut être un pool de threads, voire même être réparti sur d'autres systèmes d'un cluster et effectuer des opérations telles que l'exécution par lots ponctuelle, etc.

Il suffit de regarder ce que chacun propose de décider.

Voici d'autres bonnes pratiques concernant l'utilisation du minuteur:

http://tech.puredanger.com/2008/09/22 / timer-rules /

En général, j'utiliserais Timer pour les commandes rapides et sales et Executor pour une utilisation plus robuste.

La raison pour laquelle je préfère parfois préférer Timer à Executors.newSingleThreadScheduledExecutor () est que je reçois un code beaucoup plus propre lorsque j'ai besoin du minuteur pour qu'il s'exécute sur des threads de démon.

comparer

private final ThreadFactory threadFactory = new ThreadFactory() {
    public Thread newThread(Runnable r) {
        Thread t = new Thread(r);
        t.setDaemon(true);
        return t;
    }
};
private final ScheduledExecutorService timer = Executors.newSingleThreadScheduledExecutor(threadFactory); 

avec

private final Timer timer = new Timer(true);

Je le fais quand je n'ai pas besoin de la robustesse d'un service d'exécution.

À partir de la page de documentation d'Oracle sur ScheduledThreadPoolExecutor

  

Un ThreadPoolExecutor qui peut en outre planifier l'exécution de commandes après un délai donné ou périodiquement. Cette classe est préférable à Minuteur lorsque plusieurs threads de travail sont requis ou lorsque la flexibilité ou les fonctionnalités supplémentaires de ThreadPoolExecutor (que cette classe étend) sont requises.

ExecutorService / ThreadPoolExecutor ou ScheduledThreadPoolExecutor est un choix évident lorsque vous avez plusieurs threads de travail.

Avantages de ExecutorService sur Minuterie

  1. Timer ne peut tirer parti des cœurs de processeur disponibles, contrairement à ExecutorService , en particulier pour plusieurs tâches utilisant des variantes de ExecutorService comme ForkJoinPool
  2. ExecutorService fournit une API collaborative si vous avez besoin d'une coordination entre plusieurs tâches. Supposons que vous deviez soumettre un nombre N de tâches de travail et attendre qu'elles soient toutes terminées. Vous pouvez facilement y parvenir avec invokeAll API. Si vous souhaitez obtenir le même résultat avec plusieurs tâches Timer , cela ne sera pas simple.
  3. ThreadPoolExecutor fournit une meilleure API pour la gestion du cycle de vie des threads.

      

    Les pools de threads traitent deux problèmes différents: ils offrent généralement de meilleures performances lors de l’exécution d’un grand nombre de tâches asynchrones, en raison de la réduction du temps d’appel par tâche, et ils permettent de limiter et de gérer les ressources, y compris les threads, utilisées lors de l’exécution. une collection de tâches. Chaque ThreadPoolExecutor gère également des statistiques de base, telles que le nombre de tâches terminées.

    Peu d'avantages:

    a. Vous pouvez créer / gérer / contrôler le cycle de vie de Threads & amp; optimiser les coûts de création de threads

    b. Vous pouvez contrôler le traitement des tâches (Work Stealing, ForkJoinPool, invokeAll), etc.

    c. Vous pouvez surveiller la progression et la santé des threads

    d. Fournit un meilleur mécanisme de gestion des exceptions

Licencié sous: CC-BY-SA avec attribution
Non affilié à StackOverflow
scroll top