Minuterie et TimerTask vs + fil de sommeil en Java
-
12-09-2019 - |
Question
J'ai trouvé des questions similaires posées ici, mais il n'y avait pas de réponse à ma satisfaction. Donc, reformulant à nouveau la question -
J'ai une tâche qui doit être fait sur une base périodique (disons intervalles 1 minute). Quel est l'avantage d'utiliser TimerTask & Timer pour le faire plutôt que de créer un nouveau thread qui a une boucle infinie avec le sommeil?
Extrait de code en utilisant TimerTask -
TimerTask uploadCheckerTimerTask = new TimerTask(){
public void run() {
NewUploadServer.getInstance().checkAndUploadFiles();
}
};
Timer uploadCheckerTimer = new Timer(true);
uploadCheckerTimer.scheduleAtFixedRate(uploadCheckerTimerTask, 0, 60 * 1000);
extrait de code à l'aide de cette discussion et le sommeil -
Thread t = new Thread(){
public void run() {
while(true) {
NewUploadServer.getInstance().checkAndUploadFiles();
Thread.sleep(60 * 1000);
}
}
};
t.start();
Je n'ai vraiment pas à vous inquiéter si je manque certains cycles si l'exécution de la logique prend plus l'intervalle de temps.
S'il vous plaît commenter ce ..
Mise à jour:
Récemment, je trouve une autre différence entre l'utilisation de la minuterie par rapport Thread.sleep (). Supposons que le temps système actuel est 11:00. Si nous Rollback l'heure du système à 10h00 pour une raison quelconque, la minuterie ARRÊTER exécution de la tâche jusqu'à ce qu'il ait atteint 11:00, alors que la méthode Thread.sleep () continuerait d'exécuter la tâche sans entrave. Cela peut être un décideur important pour décider ce qu'il faut utiliser entre ces deux.
La solution
L'avantage de TimerTask est qu'il exprime votre intention beaucoup mieux (à savoir la lisibilité du code), et il a déjà la fonction d'annulation () mis en œuvre.
Notez qu'il peut être écrit sous une forme plus courte, ainsi que votre propre exemple:
Timer uploadCheckerTimer = new Timer(true);
uploadCheckerTimer.scheduleAtFixedRate(
new TimerTask() {
public void run() { NewUploadServer.getInstance().checkAndUploadFiles(); }
}, 0, 60 * 1000);
Autres conseils
Timer / TimerTask prend également en compte le temps d'exécution de votre tâche, il sera un peu plus précis. Et il traite mieux les problèmes multithreading (par exemple en évitant les blocages, etc.). Et bien sûr, il est généralement préférable d'utiliser le code standard bien testé au lieu de une solution maison.
Je ne sais pas pourquoi, mais un programme que j'écrivais utilisais Timers et sa taille de tas est en constante augmentation, une fois que je l'ai changé Enfilez / problème de sommeil résolu.
Si vous enfilez obtenir exception et se fasse tuer, c'est un problème. Mais TimerTask prendra soin. Il fonctionnera indépendamment de l'échec dans l'exécution précédente.
Il y a un argument essentiel contre la gestion de cette tâche à l'aide des threads Java et la méthode de sleep
. Vous utilisez while(true)
rester indéfiniment dans la boucle et mise en veille prolongée le fil en mettant à dormir. Que faire si NewUploadServer.getInstance().checkAndUploadFiles();
prend des ressources synchronisées. D'autres sujets ne pourront pas avoir accès à ces ressources, la famine peut se produire qui peut ralentir votre application entière. Ces types d'erreurs sont difficiles à diagnostiquer et il est une bonne idée pour éviter leur existance.
L'autre aproche déclenche l'exécution du code qui compte pour vous, à savoir NewUploadServer.getInstance().checkAndUploadFiles();
en appelant la méthode de run()
de votre TimerTask
tout en laissant d'autres threads en utilisant les ressources entre-temps.
De la Timer
documentation :
Java 5.0 introduit le paquet java.util.concurrent et l'un des utilitaires de simultanéité est dans celle-ci le ScheduledThreadPoolExecutor qui est un pool de threads pour les tâches d'exécution à plusieurs reprises à un taux donné ou retard. Il est effectivement un remplacement plus polyvalent pour la combinaison Timer / TimerTask, car il permet des fils de services multiples, accepte différentes unités de temps, et ne nécessite pas subclassing TimerTask (Mettre en œuvre juste Runnable). Configuration ScheduledThreadPoolExecutor avec un fil en fait équivalent à la minuterie.
Préférez ScheduledThreadExecutor
au lieu de Timer
:
-
Timer
utilise fil d'arrière-plan unique qui est utilisé pour exécuter toutes les tâches de la minuterie, de façon séquentielle. Ainsi, les tâches doivent remplir rapidement sinon il va retarder l'exécution des tâches suivantes. Mais en cas deScheduledThreadPoolExecutor
nous pouvons configurer un nombre de threads et peut également avoir un contrôle complet en fournissantThreadFactory
. -
Timer
peut être sensible à l'horloge du système car il rend l'utilisation de la méthode deObject.wait(long)
. MaisScheduledThreadPoolExecutor
n'est pas. - Exceptions d'exécution lancées dans TimerTask tueront ce fil particulier, rendant ainsi la minuterie mort alors que nous pouvons gérer que
ScheduledThreadPoolExecutor
afin que les autres tâches ne sont pas concernés. -
Timer
fournit la méthodecancel
de mettre fin à la minuterie et éliminer toutes les tâches planifiées, mais il ne gêne pas la tâche en cours d'exécution et laissez-le terminer. Mais si la minuterie est en cours d'exécution en tant que fils de démon alors si nous annulons ou non, il prendra fin dès que tous les fils de l'utilisateur sont finis d'exécution.
minuterie vs Thread.sleep
minuterie utilise Object.wait
et il est différent de Thread.sleep
- Une attente (
wait
) fil peut être notifié (en utilisantnotify
) par un autre thread mais on ne peut pas dormir être, il ne peut être interrompue. - Une attente (et aviser) doivent se produire dans un bloc synchronisé sur l'objet de l'écran alors que le sommeil ne fonctionne pas.
- Pendant le sommeil ne libère pas le verrou, l'attente va libérer le verrou pour l'attente d'objet est appelé.
Je pense que je comprends votre question, je vois quelque chose de très similaire. J'ai minuteries qui sont récurrents, quelques toutes les 30 minutes et quelques tous les deux jours. D'après ce que je lis et les commentaires que je vois, il semble que la collecte des ordures ne sera jamais exécutée car toutes les tâches ne sont jamais complètes. Je pense que la collecte des ordures serait exécuté quand une minuterie est en sommeil, mais je ne suis pas le voir et selon la documentation, il ne fonctionne pas.
Je pense que de nouvelles discussions fraie complète et permettre la collecte des ordures.
Quelqu'un s'il vous plaît me prouver, réécrire ce que je hérité va être une douleur.