Java possède un thread spécial, le thread démon, qui a une très faible priorité et ne sera exécuté que lorsque les autres threads du même programme ne s'exécutent pas.
Étant donné que les threads démons ont ces caractéristiques, ils sont généralement utilisés pour fournir des services aux threads ordinaires (également appelés threads utilisateur) dans le programme. Ils ont généralement une boucle infinie, ou sont utilisés pour attendre des services de requête, ou pour effectuer des tâches, etc. Ils ne peuvent effectuer aucun travail important car nous ne savons pas quand du temps CPU leur sera alloué, et ils se termineront automatiquement lorsqu'aucun autre thread ne sera en cours d'exécution. Une application typique de ce type de thread est le garbage collection Java.
Dans l'exemple de cette section, nous allons créer deux threads, l'un est un thread normal, qui écrit les événements dans la file d'attente ; l'autre est un thread démon, qui efface les événements dans la file d'attente et supprime les événements qui existent depuis plus de 10 secondes.
je le sais
Suivez les étapes ci-dessous pour implémenter l’exemple de programme.
1. Créez une classe Event, qui est uniquement utilisée pour enregistrer les informations d'événement requises pour l'exécution du programme. Déclarez deux propriétés, l'une est la propriété date du type java.util.Date et l'autre est la propriété event du type String ; puis générez les méthodes de lecture et d'écriture pour ces deux propriétés. Le code est le suivant :
Copiez le code comme suit :
Événement de classe publique {
date privée ;
événement de chaîne privé ;
Date publique getDate() {
date de retour ;
}
public void setDate (Date date) {
this.date = date ;
}
chaîne publique getEvent() {
événement de retour ;
}
public void setEvent (événement String) {
this.event = événement ;
}
}
2. Créez une classe nommée WriterTask et implémentez l'interface Runnable. Le code est le suivant :
Copiez le code comme suit :
la classe publique WriterTask implémente Runnable {
3. Déclarez un attribut de file d'attente utilisé pour stocker les événements, implémentez le constructeur de la classe et utilisez ses paramètres pour initialiser l'attribut de file d'attente. Le code est le suivant :
Copiez le code comme suit :
privé Deque<Event> deque ;
public WriterTask(Deque<Event> deque) {
this.deque = deque;
}
4. Implémentez la méthode run() de cette tâche, qui contient une boucle qui parcourt 100 fois. À chaque parcours, un nouvel objet Event est créé, puis enregistré dans la file d'attente et dort pendant 1 seconde. Le code est le suivant :
Copiez le code comme suit :
@Outrepasser
public void run() {
pour (int je = 0; je < 100; i++) {
Événement event = new Event();
event.setDate(nouvelle Date());
event.setEvent(String.format("Le thread %s a généré un événement",
Thread.currentThread().getId()));
deque.addFirst (événement);
essayer {
TimeUnit.SECONDS.sleep(1);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
5. Créez une classe nommée CleanerTask et héritez de la classe Thread. Le code est le suivant :
Copiez le code comme suit :
la classe publique CleanerTask étend le fil {
6. Déclarez un attribut de file d'attente utilisé pour stocker les événements, implémentez le constructeur de la classe et utilisez ses paramètres pour initialiser l'attribut de file d'attente. Dans la méthode de construction, définissez le thread comme thread démon en appelant la méthode setDaemon(). Le code est le suivant :
Copiez le code comme suit :
privé Deque<Event> deque ;
public CleanerTask(Deque<Event> deque) {
this.deque = deque;
setDaemon(vrai);
}
7. Implémentez la méthode run(). Il y a une boucle infinie dans le corps de la méthode pour obtenir l'heure actuelle, puis appelez la méthode clearn(). Le code est le suivant :
Copiez le code comme suit :
@Outrepasser
public void run() {
tandis que (vrai) {
Date date = nouvelle Date();
nettoyer (date);
}
}
8. Implémentez la méthode clean(). Dans cette méthode, obtenez la dernière heure, puis vérifiez le décalage horaire entre l'heure et l'heure actuelle. S'il a été créé il y a 10 secondes, supprimez l'événement en cours, puis vérifiez le suivant. événement. Si un événement est supprimé, les informations sur l'événement supprimé seront imprimées, ainsi que la dernière longueur de la file d'attente, afin que la progression de l'exécution du programme puisse être observée. Le code est le suivant :
Copiez le code comme suit :
privé vide propre (Date date) {
longue différence;
suppression booléenne ;
si (deque.size() == 0) {
retour;
}
supprimer = faux ;
faire {
Événement e = deque.getLast();
différence = date.getTime() - e.getDate().getTime();
si (différence > 10000) {
System.out.printf("Nettoyeur : %s/n", e.getDate());
deque.removeLast();
supprimer = vrai ;
}
} while (différence > 10000) ;
si (supprimer) {
System.out.printf("Clearner : Taille de la file d'attente : %d/n", deque.size());
}
}
9. Créez la classe principale du programme, la classe Main, puis implémentez la méthode main(). Le code est le suivant :
Copiez le code comme suit :
classe publique Principale {
public static void main (String[] arguments) {
10. Utilisez la classe Deque pour créer une file d'attente pour stocker les événements. Le code est le suivant :
Copiez le code comme suit :
Deque<Événement> deque = new ArrayDeque<>();
11. Créez et démarrez trois threads WriterTask et un thread CleanerTask. Le code est le suivant :
Copiez le code comme suit :
Deque<Événement> deque = new ArrayDeque<>();
WriterTask écrivain = new WriterTask(deque);
pour (int je = 0; je < 3; i++) {
Fil de discussion = nouveau Thread(écrivain);
thread.start();
}
CleanerTask Cleaner = new CleanerTask(deque);
nettoyeur.start();
12. Exécutez le programme et affichez les résultats de l'exécution.
sais pourquoi
En analysant les résultats de l'exécution du programme, nous pouvons voir que la file d'attente augmente d'abord jusqu'à 30, puis change entre 27 et 30 jusqu'à la fin de l'exécution du programme.
Le programme commence d'abord à s'exécuter à partir de trois threads WriterTask. Chaque thread ajoute d'abord un événement à la file d'attente, puis se met en veille pendant 1 seconde. Après les 10 premières secondes, il y aura trente événements dans la file d'attente. Pendant ces 10 secondes, lorsque les trois threads WriterTask sont en veille, le thread CleanerTask s'exécutera également, mais aucun événement ne sera supprimé car le temps de génération de tous les événements ne dépasse pas 10 secondes. Après les 10 premières secondes, trois WriterTasks ajoutent trois événements à la file d'attente chaque seconde ; de la même manière, CleanerTask supprime trois événements chaque seconde ; Le nombre d’événements oscille donc entre 27 et 30.
Lorsque les threads WriterTask sont tous en veille, nous sommes libres de traiter le temps, permettant au thread démon de s'exécuter pendant ce temps. Si vous définissez le temps de veille du thread WriterTask pour qu'il soit plus court, le thread CleanerTask bénéficiera de moins de temps d'exécution du processeur. Si tel est le cas, la longueur de la file d'attente continuera de croître car le thread CleanerTask ne dispose jamais de suffisamment de temps d'exécution pour supprimer suffisamment d'événements.
sans fin
Le thread ne peut être défini comme thread démon qu'en appelant la méthode setDaemon() avant d'appeler la méthode start(). Une fois qu'un thread commence à s'exécuter, l'état du démon ne peut plus être modifié.
Vous pouvez également utiliser isDaemon() pour vérifier si un thread est un thread démon. S'il s'agit d'un thread démon, il renvoie vrai ; s'il s'agit d'un thread ordinaire, il renvoie faux.
Utiliser la doctrine
Cet article est traduit du "Java 7 Concurrency Cookbook" (D Gua Ge l'a volé sous le nom de "Java7 Concurrency Sample Collection") et n'est utilisé que comme matériel d'apprentissage. Il ne peut être utilisé à des fins commerciales sans autorisation.
Petit succès
Versions complètes de tous les exemples de code utilisés dans cette section.
Code complet de la classe Event
Copiez le code comme suit :
package com.diguage.books.concurrencycookbook.chapter1.recipe7;
importer java.util.Date ;
/**
*Cours d'information sur l'événement
* Date : 2013-09-19
* Heure : 22h56
*/
Événement de classe publique {
date privée ;
événement de chaîne privé ;
Date publique getDate() {
date de retour ;
}
public void setDate (Date date) {
this.date = date ;
}
chaîne publique getEvent() {
événement de retour ;
}
public void setEvent (événement String) {
this.event = événement ;
}
}
Code complet de la classe WriterTask
Copiez le code comme suit :
package com.diguage.books.concurrencycookbook.chapter1.recipe7;
importer java.util.Date ;
importer java.util.Deque ;
importer java.util.concurrent.TimeUnit ;
/**
* Générez un événement chaque seconde.
* Date : 2013-09-19
* Heure : 22h59
*/
la classe publique WriterTask implémente Runnable {
privé Deque<Event> deque ;
public WriterTask(Deque<Event> deque) {
this.deque = deque;
}
@Outrepasser
public void run() {
pour (int je = 0; je < 100; i++) {
Événement event = new Event();
event.setDate(nouvelle Date());
event.setEvent(String.format("Le thread %s a généré un événement",
Thread.currentThread().getId()));
deque.addFirst (événement);
essayer {
TimeUnit.SECONDS.sleep(1);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
}
Code complet de la classe CleanerTask
Copiez le code comme suit :
package com.diguage.books.concurrencycookbook.chapter1.recipe7;
importer java.util.Date ;
importer java.util.Deque ;
/**
* Nettoyage d'événements
* Date : 2013-09-19
* Heure : 23h33
*/
la classe publique CleanerTask étend le fil {
privé Deque<Event> deque ;
public CleanerTask(Deque<Event> deque) {
this.deque = deque;
setDaemon(vrai);
}
@Outrepasser
public void run() {
tandis que (vrai) {
Date date = nouvelle Date();
nettoyer (date);
}
}
/**
* Supprimer l'événement.
*
* @paramdate
*/
privé vide propre (Date date) {
longue différence;
suppression booléenne ;
si (deque.size() == 0) {
retour;
}
supprimer = faux ;
faire {
Événement e = deque.getLast();
différence = date.getTime() - e.getDate().getTime();
si (différence > 10000) {
System.out.printf("Nettoyeur : %s/n", e.getDate());
deque.removeLast();
supprimer = vrai ;
}
} while (différence > 10000) ;
si (supprimer) {
System.out.printf("Clearner : Taille de la file d'attente : %d/n", deque.size());
}
}
}
Le code complet de la classe Main
Copiez le code comme suit :
package com.diguage.books.concurrencycookbook.chapter1.recipe7;
importer java.util.ArrayDeque ;
importer java.util.Deque ;
/**
* Date : 2013-09-19
* Heure : 23h54
*/
classe publique Principale {
public static void main (String[] arguments) {
Deque<Événement> deque = new ArrayDeque<>();
WriterTask écrivain = new WriterTask(deque);
pour (int je = 0; je < 3; i++) {
Fil de discussion = nouveau Thread(écrivain);
thread.start();
}
CleanerTask Cleaner = new CleanerTask(deque);
nettoyeur.start();
}
}