arrière-plan
Pendant le développement du projet, nous devons souvent effectuer des tâches périodiques. Cela peut nous aider à bien y parvenir grâce à des tâches de synchronisation.
Comparons plusieurs cadres de tâches chronométrés couramment utilisés:
Comme on peut le voir dans le tableau ci-dessus, le cadre du calendrier de printemps a des fonctions complètes et est simple et facile à utiliser. Le calendrier de printemps est entièrement qualifié pour les petits et moyens projets.
1. Horaire d'intégration Springboot
1.1 Ajout d'un ensemble de dépendances Maven
Étant donné que le calendrier de printemps est inclus dans le module de base de Spring-Boot-Starter, aucune dépendance supplémentaire n'est requise.
<Dependances> <Dependency> <GroupId> org.springframework.boot </proupId> <ArtifActid> printemps-boot-starter </ artifactid> </pedigency> <dependency> <prouprid> org.springframework.boot </pr grouped> <ptetifactid> Spring-Boot-starter-test </ artifactid> </dpendance> </dpendances>
1.2 Classe de démarrage, ajouter l'annotation des startups
L'ajout de l'annotation @EnablesCeduling à la classe de saisie ou de configuration Springboot peut activer les tâches de synchronisation.
@ ActiveScheduling @ SpringbootApplicationPublic Class ScheduleApplication {public static void main (String [] args) {SpringApplication.run (scheduleApplication.class, args);}}1.3. Ajouter les tâches chronométrées
Nous donnerons des exemples des trois planificateurs de tâches du calendrier de printemps.
1.3.1 Cron Expressions
Similaire aux règles de définition du temps d'expression CRON sous Linux. Une expression Cron se compose de 6 ou 7 espaces séparés par des champs de temps, comme indiqué dans la figure ci-dessous:
Expressions courantes:
Prenez un châtaignier:
Ajoutez une méthode work (), qui est exécutée toutes les 10 secondes.
Remarque: Lorsque l'heure d'exécution de la méthode dépasse la fréquence de planification des tâches, le planificateur s'exécutera dans le cycle suivant.
Par exemple: en supposant que la méthode work () commence à être exécutée à la 0e seconde et que la méthode est exécutée pendant 12 secondes, la prochaine fois que la méthode Work () sera exécutée est la 20e seconde.
@ComponentPublic class mytask {@scheduled (cron = "0/10 * * * * *") public void work () {// Logique d'exécution de la tâche}}1.3.2 Tâches à intervalles fixes
Le temps d'exécution de la tâche suivant est calculé à partir de la fin de la dernière exécution de la tâche de la méthode. Et commencer l'exécution périodique des tâches avec cette règle.
Prenez un châtaignier:
Ajoutez une méthode work () et exécutez-la toutes les 10 secondes.
Par exemple: Supposons que la méthode Work () commence à être exécutée à la 0e seconde et que la méthode est exécutée pendant 12 secondes, la prochaine fois que la méthode Work () sera exécutée est la 22e seconde.
@Scheduled (fixedelay = 1000 * 10) public void work () {// Logique d'exécution de la tâche}1.3.3 Tâches de fréquence fixe
Exécutez des tâches à la fréquence spécifiée et démarrez l'exécution périodique de la planification avec cette règle.
Prenez un châtaignier:
Ajoutez une méthode work (), qui est exécutée toutes les 10 secondes.
Remarque: Lorsque l'heure d'exécution de la méthode dépasse la fréquence de planification des tâches, le planificateur exécutera la tâche suivante immédiatement après l'exécution de la méthode actuelle.
Par exemple: Supposons que la méthode Work () commence à être exécutée à la 0e seconde et que la méthode est exécutée pendant 12 secondes, la prochaine fois que la méthode Work () sera exécutée est la 12e seconde.
@Scheduled (fixerate = 1000 * 10) public void work () {// Logique d'exécution de la tâche}2. Configurez le pool de threadscheler tasksCheduler
Dans les projets réels, notre système peut définir plusieurs tâches de synchronisation. Ensuite, plusieurs tâches de synchronisation peuvent être effectuées indépendamment et en parallèle.
En regardant le code source d'org.springframework.scheduling.config.scheduledTaskRegistrar, il est constaté que Spring créera un pool unique par défaut. Cela peut être fatal pour notre multitâche. Lorsque plusieurs tâches sont exécutées simultanément (ou doivent être exécutées en même temps), le planificateur de tâches connaîtra la dérive du temps et le temps d'exécution des tâches sera incertain.
Protégé de void scheduleTasks () {if (this.taskscheduler == null) {this.localexecutor = exécutor this.taskscheduler = new concurrentTasksCheduler (this.localexecutor);} // omettre ...}2.1 Pool de thread personnalisé
Ajout d'une classe de configuration pour implémenter l'interface SchedulingConfigurer. Réécrivez la méthode ConfigureTasks et définissez un pool de thread personnalisé via TaskRegistrar.
@ConfigurationPublic Class ScheduleConfig implémente SchedulingConfigurer {@OverRidePublic void ConfigureAsks (ScheduledTaskRegistrar TaskRegistrar) Exécutors.NewScheduledThreadpool (20);}}3. Problèmes dans les applications pratiques
3.1 Problèmes de démarrage et d'arrêt dans les applications Web
Nous savons que les haricots chargés ou initialisés via le ressort seront automatiquement déchargés (détruits) lorsque le service est arrêté. Cependant, comme les threads sont de niveau JVM, si l'utilisateur démarre un thread dans une application Web, le cycle de vie de ce fil ne sera pas cohérent avec l'application Web. C'est-à-dire, même si l'application Web s'arrête, le fil ne se termine toujours pas (mort).
Solution:
1) L'objet actuel est initialisé par le ressort
Lorsque le printemps désinstalle (détruit) une instance, la méthode de détruire de l'instance sera appelée. Implémenté en implémentant l'interface DisposableBean Omposant la méthode de détruire. Fermez activement le fil dans la méthode Detrère.
@ComponentPublic class MyTask implémente DisposableBean {@OverRidePublic void destrust () lève exception {// Fermer le thread ou le filetage ThreadPoolTasksCheduler Scheduler = (ThreadPoolTasksCheDuler) ApplicationContext.getBean ("Scheduler"); Scheduler.Shutdown ();} // Omit ...}2) L'objet actuel n'est pas initialisé (géré) au printemps
Ensuite, nous pouvons ajouter un auditeur de contexte de servlet pour fermer activement le fil lorsque le service de servlet est arrêté.
classe publique MyTaskListEnter implémente ServletContextListener {@OverRidePublic void contextDestRoyed (servletContexTevent arg0) {// Fermer Thread ou Thread Pool} // Omit ...}3.2 Problèmes de déploiement distribué
Dans les projets réels, notre système sera généralement déployé en clusters, distribué ou catastrophe. Ensuite, les tâches de synchronisation peuvent avoir des problèmes de concurrence, c'est-à-dire que la même tâche fonctionne sur plusieurs serveurs en même temps.
Solution (verrouillage distribué):
1) Verrouiller la table de base de données
2) Cache middleware
3) implémenté via Zookeeper
Résumer:
Le calendrier de printemps nous fournit un cadre de tâche de synchronisation simple, rapide, efficace et stable. Cependant, il est nécessaire de considérer le cycle de vie des fils et des problèmes de déploiement distribués.
Ce qui précède est tout le contenu de cet article. J'espère que cela sera utile à l'apprentissage de tous et j'espère que tout le monde soutiendra davantage Wulin.com.