Dans la section précédente "Interruption du thread", nous avons expliqué comment interrompre un thread en cours d'exécution et ce que nous devons faire au thread afin d'interrompre le thread. En général, nous pouvons utiliser le mécanisme d’interruption introduit dans la section précédente. Cependant, si le thread implémente un algorithme complexe réparti entre plusieurs méthodes, ou s'il y a un appel récursif dans l'appel de méthode, nous devrions utiliser une meilleure façon de contrôler l'interruption du thread. À cette fin, Java fournit InterruptedException. Cette exception peut être levée lorsqu'une demande d'interruption est détectée et interceptée dans la méthode run().
Dans cette section, nous utiliserons un thread pour rechercher des fichiers dans un répertoire spécifié et ses sous-répertoires afin de démontrer le contrôle de l'interruption du thread à l'aide d'InterruptedException.
je le sais
Suivez les étapes indiquées ci-dessous pour implémenter l’exemple de programme.
1. Créez une classe nommée FileSearch et implémentez l'interface Runnable. Le code est le suivant :
Copiez le code comme suit :
la classe publique FileSearch implémente Runnable {
2. Déclarez deux variables, une pour le nom du fichier à rechercher et une pour initialiser le répertoire à rechercher ; implémentez le constructeur de la classe, et initialisez les deux variables qui viennent d'être déclarées avec les paramètres du constructeur. Le code est le suivant :
Copiez le code comme suit :
chaîne privée initPath ;
nom de fichier de chaîne privé ;
public FileSearch (String initPath, String fileName) {
this.initPath = initPath;
this.fileName = fileName;
}
3. Implémentez la méthode run(), qui vérifie si fileName est un nom de chemin. Si tel est le cas, appelez la méthode directoryProcess() pour le traitement. La méthode directoryProcess() renvoie InterruptedException, nous devons donc intercepter l'exception. Le code est le suivant :
Copiez le code comme suit :
@Outrepasser
public void run() {
Fichier fichier = nouveau fichier (initPath);
si (file.isDirectory()) {
essayer {
répertoireProcess(fichier);
} catch (InterruptedException e) {
System.out.printf("%s : La recherche a été interrompue",
Thread.currentThread().getName());
}
}
}
Dans l'article original, le nom de la méthode mentionné est processDirectory(). Cependant, selon la procédure ci-dessous, il s'agit d'une erreur matérielle. Alors corrigez-le.
4. Implémentez la méthode directoryProcess(). Cette méthode lit tous les fichiers et sous-répertoires du répertoire spécifié, puis les traite. Pour chaque répertoire, cette méthode effectue un appel récursif pour traiter le répertoire spécifié par le paramètre. Pour chaque fichier, cette méthode appelle la méthode fileProcess(). Après avoir traité tous les répertoires et fichiers, cette méthode vérifiera si le thread est interrompu, ce qui revient à lever une exception InterruptedException. Le code est le suivant :
Copiez le code comme suit :
/**
* Traiter un répertoire
*
* Répertoire du fichier @param à traiter
* @throws InterruptedException
*/
private void directoryProcess (fichier fichier) lance InterruptedException {
Fichier[] list = fichier.listFiles();
if (null != liste) {
pour (int i = 0; i < list.length; i++) {
si (liste[i].isDirectory()) {
répertoireProcess(liste[i]);
} autre {
fileProcess(liste[i]);
}
}
}
si (Thread.interrupted()) {
lancer une nouvelle InterruptedException();
}
}
5. Implémentez la méthode fileProcess(), qui compare le fichier en cours de traitement avec le nom du fichier à trouver. Si les noms de fichiers sont égaux, un message est imprimé sur la console. Le thread vérifie ensuite s’il a été interrompu et, si c’est le cas, lève une InterruptedException. Le code est le suivant :
Copiez le code comme suit :
/**
* Fichiers traités
*
* @param file fichier à traiter
* @throws InterruptedException
*/
private void fileProcess (fichier fichier) lance InterruptedException {
if (file.getName().equals(fileName)) {
System.out.printf("%s : %s/n",
Thread.currentThread().getName(),
fichier.getAbsolutePath());
}
si (Thread.interrupted()) {
lancer une nouvelle InterruptedException();
}
}
6. Maintenant, implémentez la classe principale de l’exemple et 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) {
7. Créez et initialisez l'objet FileSearch, puis créez un objet Thread pour effectuer la tâche. Ensuite, démarrez le fil. Le code est le suivant :
Copiez le code comme suit :
FileSearch fileSearch = new FileSearch("C://", "autoexec.bat");
Fil de discussion = nouveau fil (fileSearch);
thread.start();
8. Attendez dix secondes, puis interrompez le fil. Le code est le suivant :
Copiez le code comme suit :
essayer {
TimeUnit.SECONDS.sleep(10);
} catch (InterruptedException e) {
e.printStackTrace();
}
thread.interrupt();
9. Exécutez l'exemple et affichez les résultats.
sais pourquoi
Ce qui suit est le résultat de l'exécution du thread. La sortie montre comment l'exécution du thread se termine lorsque FileSearch détecte qu'elle a été interrompue.
Copiez le code comme suit :
Fil de discussion 0 : C:/autoexec.bat
Sujet 0 : La recherche a été interrompue
Dans cet exemple, nous utilisons des exceptions Java pour contrôler l'interruption des threads. Lorsque vous exécutez l'exemple, le programme vérifie si le répertoire spécifié et ses sous-répertoires contiennent le fichier cible. Par exemple, si vous entrez /b/c/d, le programme appellera récursivement la méthode directoryProcess() trois fois. Lorsque le thread détecte qu'il a été interrompu, une InterruptedException sera levée. Quel que soit le nombre d'appels récursifs effectués, le programme commencera à exécuter la méthode run().
sans fin
Les exceptions InterruptedException sont généralement levées par les API de concurrence Java, telles que la méthode sleep().
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
Le code complet de la classe FileSearch est le suivant :
package com.diguage.books.concurrencycookbook.chapter1.recipe4 ;
importer java.io.File ;
/**
* Date : 2013-09-18
* Heure : 18h21
*/
la classe publique FileSearch implémente Runnable {
chaîne privée initPath ;
nom de fichier de chaîne privé ;
/**
* Constructeur d'initialisation
*
* @param initPath Le répertoire dans lequel rechercher
* @param fileName Le nom du fichier à trouver
*/
public FileSearch (String initPath, String fileName) {
this.initPath = initPath;
this.fileName = fileName;
}
@Outrepasser
public void run() {
Fichier fichier = nouveau fichier (initPath);
si (file.isDirectory()) {
essayer {
répertoireProcess(fichier);
} catch (InterruptedException e) {
System.out.printf("%s : La recherche a été interrompue",
Thread.currentThread().getName());
}
}
}
/**
* Traiter un répertoire
*
* Répertoire du fichier @param à traiter
* @throws InterruptedException
*/
private void directoryProcess (fichier fichier) lance InterruptedException {
Fichier[] list = fichier.listFiles();
if (null != liste) {
pour (int i = 0; i < list.length; i++) {
si (liste[i].isDirectory()) {
répertoireProcess(liste[i]);
} autre {
fileProcess(liste[i]);
}
}
}
si (Thread.interrupted()) {
lancer une nouvelle InterruptedException();
}
}
/**
* Fichiers traités
*
* @param file fichier à traiter
* @throws InterruptedException
*/
private void fileProcess (fichier fichier) lance InterruptedException {
if (file.getName().equals(fileName)) {
System.out.printf("%s : %s/n",
Thread.currentThread().getName(),
fichier.getAbsolutePath());
}
si (Thread.interrupted()) {
lancer une nouvelle InterruptedException();
}
}
}
Le code complet de la classe Main
Copiez le code comme suit :
package com.diguage.books.concurrencycookbook.chapter1.recipe4;
importer java.util.concurrent.TimeUnit ;
/**
* Date : 2013-09-18
* Heure : 19h28
*/
classe publique Principale {
public static void main (String[] arguments) {
FileSearch fileSearch = new FileSearch("C://", "autoexec.bat");
Fil de discussion = nouveau fil (fileSearch);
thread.start();
essayer {
TimeUnit.SECONDS.sleep(10);
} catch (InterruptedException e) {
e.printStackTrace();
}
thread.interrupt();
}
}