Salut tout le monde,
Je dois ré-écrire en Java la commande UNIX find
* limitée au cas d'utilisation suivant : find <file> <dir>
.
Le traitement de chaque répertoire doit être pris en charge par un thread Java. De plus, mon programme doit compter le nombre de répertoires traversés (une variable statique protégée sera utilisée pour ce faire, et le thread main
en affichera le contenu à la fin de l'exécution).
Problèmes
La solution que j'ai trouvée fonctionne à peu près. Cependant, deux problèmes subsistent :
-
L'affichage de ce contenu n'attend pas la fin de tous les threads-fils et affiche toujours
0
. -
Lorsqu'un processus-fils a trouvé le fichier recherché, il faudrait stopper tous les processus-fils (ces derniers polluent la console avec leurs messages "Searching in the directory…", qui continuent de s'afficher après le message "File was found here").
Concernant le problème n°1, mon thread-main n'attend pas que ses processus-fils aient pris fin, il tente donc d'afficher la variable statique alors même que celle-ci n'a pas encore été valuée par l'un d'eux… (je pense que c'est ce qui se passe). Pour résoudre ce souci, je pense qu'il faudrait utiliser wait
et notify
?
Pour le problème n°2, j'ai cherché sur Internet comment tuer un thread Java et a priori c'est impossible… Cependant je suis sûr qu'il y a bien une solution à ce souci ?
Les sources
FICHIER : Launcher.java
1 2 3 4 5 6 7 8 | public class Launcher { public static void main(String args[]) { // Find's launch Find find = new Find("tests.txt", "C:/Users/dor/google_drive"); find.start(); System.out.println("Nombre de répertoires traversés : " + Find.number_of_dirs); } } |
FICHIER : Find.java
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 | public class Find extends Thread { private String file, dir; protected static int number_of_dirs; public Find(String file, String dir) { this.file = file; this.dir = dir; } private static synchronized void incrementNumberOfDirs() { Find.number_of_dirs++; } public void run() { this.search(this.dir); } public void search(String file_path) { File file = new File(file_path); if(file.isDirectory()) { System.out.println("Searching in the directory... " + file.getAbsolutePath()); for(File found_file : file.listFiles()) { if(found_file.isDirectory()) { Find.incrementNumberOfDirs(); Find find = new Find(this.file, found_file.getAbsolutePath()); find.start(); } else { if(this.file.equals(found_file.getName())) { System.out.println("File was found here : " + found_file.getAbsolutePath() + " !"); } } } } } } |
Le code-source précédent a été mis à jour (cf. partie "Solution avec interrupt
").
Voilà j'espère que vous pourrez une nouvelle fois m'aider =/
Bonne journée et merci !
find
* : Cette commande cherche le fichier file
dans le répertoire dir
ainsi que dans les répertoires de ce dernier, puis dans leurs propres répertoires, et ainsi de suite (ie. : commande récursive).
Solution avec interrupt
Je viens de tester un truc : pour arrêter tous les processus-fils lorsque le fichier a été trouvé, j'utilise la méthode interrupt
sur tous les threads Find
créés. Ces derniers sont stockés dans une variable statique de type ArrayList<Find>
.
Mais visiblement ça ne fait rien…
Voici le nouveau code-source :
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 | public class Find extends Thread { private static ArrayList<Find> all_threads = new ArrayList<Find>(); private String file, dir; protected static int number_of_dirs; public Find(String file, String dir) { this.file = file; this.dir = dir; synchronized (Find.class) { Find.all_threads.add(this); } } private static synchronized void incrementNumberOfDirs() { Find.number_of_dirs++; } public void run() { this.search(this.dir); } public void search(String file_path) { File file = new File(file_path); if(file.isDirectory()) { System.out.println("Searching in the directory... " + file.getAbsolutePath()); for(File found_file : file.listFiles()) { if(Find.interrupted()) { synchronized (Find.class) { Find.all_threads.remove(this); } System.out.println("ok"); return; } if(found_file.isDirectory()) { Find.incrementNumberOfDirs(); Find find = new Find(this.file, found_file.getAbsolutePath()); find.start(); } else { if(this.file.equals(found_file.getName())) { System.out.println("File was found here : " + found_file.getAbsolutePath() + " !"); Find.all_threads.forEach(thread -> thread.interrupt()); } } } } } } |