IdentifiantMot de passe
Loading...
Mot de passe oublié ?Je m'inscris ! (gratuit)
Navigation

Inscrivez-vous gratuitement
pour pouvoir participer, suivre les réponses en temps réel, voter pour les messages, poser vos propres questions et recevoir la newsletter

avec Java Discussion :

Problème avec un Thread


Sujet :

avec Java

  1. #1
    Nouveau membre du Club
    Homme Profil pro
    artisan
    Inscrit en
    Octobre 2013
    Messages
    47
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Bouches du Rhône (Provence Alpes Côte d'Azur)

    Informations professionnelles :
    Activité : artisan
    Secteur : Bâtiment

    Informations forums :
    Inscription : Octobre 2013
    Messages : 47
    Points : 30
    Points
    30
    Par défaut Problème avec un Thread
    Bonjour à tous ,

    Voici mon code de principe initial et fonctionnel :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    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
    51
    52
    53
    54
    55
    56
    57
    58
    59
    60
    61
    62
    63
    64
    65
    66
    67
    68
    69
    import java.io.BufferedReader;
    import java.io.FileNotFoundException;
    import java.io.FileReader;
    import java.io.IOException;
    import java.nio.file.Path;
    import java.nio.file.Paths;
    import java.util.StringTokenizer;
     
     
    public class Example {
     
    	static String line;
    	static boolean startNext = true;
    	static String fichiersATelecharger;
     
     
    	public static void main(String args[]) throws FileNotFoundException {
    		Path chemin = Paths.get("d:", "fichier.txt");
    		FileReader fr = new FileReader(chemin.toString());
    		BufferedReader br =  new BufferedReader (fr);
     
    	    try{
    	    	while ((line  = br.readLine()) != null) {
    	    		if (startNext){
    	            StringTokenizer token = new StringTokenizer (line);
     
    	            while(token.hasMoreTokens()){
     
    	                fichiersATelecharger=(token.nextToken());
     
     
    	                telecharger(fichiersATelecharger );
     
     
    	               }
    	            }
     
    	    	}
     
    	    } catch (IOException e) {
    	        System.out.println (e.getMessage());
    	        e.printStackTrace();
    	    } finally {
    	        try {
    				br.close();
    			} catch (IOException e) {
    				// TODO Auto-generated catch block
    				e.printStackTrace();
    			}
    	    }
    		}
     
     
    public static void telecharger (  String fichiersATelecharger ){
    	 startNext = false;
     
     
     	System.out.print(fichiersATelecharger);
     	System.out.print("\n");
     	// simulation du temps de téléchargement
     	try { 
     		  Thread.sleep(2000);
     		}
     		catch (InterruptedException exception) {
     		  exception.printStackTrace();
     		}
     	startNext = true;
    }
    }
    Ce code fonctionne et donc toutes les 2 secondes j'affiche une ligne de mon fichier.txt.

    contenu fichier.txt:
    chemin1
    chemin2
    chemin3
    chemin4
    sortie console:
    chemin1
    (2s d'attente)
    chemin2
    (2s d'attente)
    chemin3
    (2s d'attente)
    chemin4
    (2s d'attente)
    Je voudrais maintenant que l'action de la méthode telecharger() s'exécute au travers d'un Thread:
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    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
    51
    52
    53
    54
    55
    56
    57
    58
    59
    60
    61
    62
    63
    64
    65
    66
    67
    68
    69
    70
    71
    72
    73
    74
    75
    76
    77
    78
    79
    80
    81
    82
    83
    84
    85
    86
    87
    88
    89
    90
    91
    92
    import java.io.BufferedReader;
    import java.io.FileNotFoundException;
    import java.io.FileReader;
    import java.io.IOException;
    import java.nio.file.Path;
    import java.nio.file.Paths;
    import java.util.StringTokenizer;
     
     
    public class Example {
     
    	static String line;
     
    	static String fichiersATelecharger;
    	static boolean startNext = true;
     
    	public static void main(String args[]) throws FileNotFoundException {
    		Path chemin = Paths.get("d:", "fichier.txt");
    		FileReader fr = new FileReader(chemin.toString());
    		BufferedReader br =  new BufferedReader (fr);
     
    	    try{
    	    	while ((line  = br.readLine()) != null) {
    	    		if (startNext){
    	            StringTokenizer token = new StringTokenizer (line);
     
    	            while(token.hasMoreTokens()){
     
    	                fichiersATelecharger=(token.nextToken());
     
     
    	                telecharger(fichiersATelecharger );
     
     
    	               }
    	            }
     
    	    	}
     
    	    } catch (IOException e) {
    	        System.out.println (e.getMessage());
    	        e.printStackTrace();
    	    } finally {
    	        try {
    				br.close();
    			} catch (IOException e) {
    				// TODO Auto-generated catch block
    				e.printStackTrace();
    			}
    	    }
    		}
     
     
    public static void telecharger (  final String fichiersATelecharger ){
     
    	 startNext = false;
     
     
     
    	new Thread(new Runnable() {
     
     
     
    		public boolean startNext ;
     
     
            @Override
            public void run() {
            	Example.fichiersATelecharger = fichiersATelecharger;
     
            	System.out.print(fichiersATelecharger);
            	System.out.print("\n");
            	//simulation du temps de téléchargement
            	try { 
            		  Thread.sleep(2000);
            		}
            		catch (InterruptedException exception) {
            		  exception.printStackTrace();
            		}
     
            	setStartNext(true);
            }
     
    		public void setStartNext(boolean startNext) {
    			Example.startNext = startNext;
    			System.out.print(Example.startNext);
    		}
    	}).start();
     
    }
     
    }
    sortie console:
    chemin1
    (2s d'attente)
    true
    Dans ce cas je n'affiche que la première ligne de mon fichier.txt. Pourtant la valeur de Example.startNext est bien sur true ainsi que la valeur de startNext dans mon main (visible en debug avec un break point)



    Une aide ne serait pas de refus...merci d'avance

  2. #2
    Modérateur
    Avatar de joel.drigo
    Homme Profil pro
    Ingénieur R&D - Développeur Java
    Inscrit en
    Septembre 2009
    Messages
    12 430
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 54
    Localisation : France, Paris (Île de France)

    Informations professionnelles :
    Activité : Ingénieur R&D - Développeur Java
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Septembre 2009
    Messages : 12 430
    Points : 29 131
    Points
    29 131
    Billets dans le blog
    2
    Par défaut
    Salut,

    tu dois considérer que le code exécuté dans la méthode main s'éxécute dans un thread, appelons le thread main.
    Dans ce thread, quand tu appelles ta méthode telecharger(), tu passes startNext à false, puis tu lances un autre thread, qui attends 2 secondes avant de repasser startNext à true. Pendant que ce second thread attends 2 secondes, le premier continue à tourner : il continue à lire des lignes dans ton fichier, et fais un test sur startNext qui est false (tant que les 2 secondes d'attente ne sont pas passées), donc la ligne lue n'est pas traitée, donc ça passe à la suivante, ainsi de suite jusqu'à la dernière
    En 2 secondes, le premier thread a le temps de lire tout le fichier et de se terminer, et, comme je suppose qu'il n'y a qu'un token par ligne, l'itération sur les tokens, qui ne teste pas startNext, ne fait qu'un appel à telecharger(). Donc ça ne fait qu'un appel à telecharger() en tout.
    L'expression "ça marche pas" ne veut rien dire. Indiquez l'erreur, et/ou les comportements attendus et obtenus, et donnez un Exemple Complet Minimal qui permet de reproduire le problème.
    La plupart des réponses à vos questions sont déjà dans les FAQs ou les Tutoriels, ou peut-être dans une autre discussion : utilisez la recherche interne.
    Des questions sur Java : consultez le Forum Java. Des questions sur l'EDI Eclipse ou la plateforme Eclipse RCP : consultez le Forum Eclipse.
    Une question correctement posée et rédigée et vous aurez plus de chances de réponses adaptées et rapides.
    N'oubliez pas de mettre vos extraits de code entre balises CODE (Voir Mode d'emploi de l'éditeur de messages).
    Nouveau sur le forum ? Consultez Les Règles du Club.

  3. #3
    Nouveau membre du Club
    Homme Profil pro
    artisan
    Inscrit en
    Octobre 2013
    Messages
    47
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Bouches du Rhône (Provence Alpes Côte d'Azur)

    Informations professionnelles :
    Activité : artisan
    Secteur : Bâtiment

    Informations forums :
    Inscription : Octobre 2013
    Messages : 47
    Points : 30
    Points
    30
    Par défaut
    Merci pour ta réponse;

    c'est un peu confus dans mon esprit ...

    Ce que je ne comprends pas c'est que le public void run() n'est exécuté qu'à la fin et pour la valeur fichiersATelecharger == chemin1.

    Alors qu'effectivement la boucle de lecture du fichier a tout lu et donc passé fichiersATelecharger sur chemin2,3 et 4...

    Quelle approche avoir pour réaliser ce que je souhaite?

  4. #4
    Modérateur
    Avatar de joel.drigo
    Homme Profil pro
    Ingénieur R&D - Développeur Java
    Inscrit en
    Septembre 2009
    Messages
    12 430
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 54
    Localisation : France, Paris (Île de France)

    Informations professionnelles :
    Activité : Ingénieur R&D - Développeur Java
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Septembre 2009
    Messages : 12 430
    Points : 29 131
    Points
    29 131
    Billets dans le blog
    2
    Par défaut
    Ça dépend de ce que tu souhaites
    La, de ce que je peux comprendre, tu cherches à télécharger des fichiers les uns après les autres, tout en attendant entre 2 téléchargements pour lire le nom du prochain fichier à télécharger. Pas besoin d'avoir de thread pour ça : tu mets tout dans le thread main comme dans ton premier code...
    Maintenant, si tu veux charger tous les noms de fichiers pendant que tu commences à télécharger en parallèle, tu peux procéder avec un modèle producteur-consommateur : le thread main lit les fichiers, tokenize les lignes, et mets les résultats dans une liste, et le second thread, unique, lit les noms des fichiers dans cette liste, et lance un téléchargement (ou plusieurs si tu veux) à chaque fois qu'il trouve un nom dedans. Tu trouveras de nombreux exemples de ce modèle sur le net.
    L'expression "ça marche pas" ne veut rien dire. Indiquez l'erreur, et/ou les comportements attendus et obtenus, et donnez un Exemple Complet Minimal qui permet de reproduire le problème.
    La plupart des réponses à vos questions sont déjà dans les FAQs ou les Tutoriels, ou peut-être dans une autre discussion : utilisez la recherche interne.
    Des questions sur Java : consultez le Forum Java. Des questions sur l'EDI Eclipse ou la plateforme Eclipse RCP : consultez le Forum Eclipse.
    Une question correctement posée et rédigée et vous aurez plus de chances de réponses adaptées et rapides.
    N'oubliez pas de mettre vos extraits de code entre balises CODE (Voir Mode d'emploi de l'éditeur de messages).
    Nouveau sur le forum ? Consultez Les Règles du Club.

  5. #5
    Nouveau membre du Club
    Homme Profil pro
    artisan
    Inscrit en
    Octobre 2013
    Messages
    47
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Bouches du Rhône (Provence Alpes Côte d'Azur)

    Informations professionnelles :
    Activité : artisan
    Secteur : Bâtiment

    Informations forums :
    Inscription : Octobre 2013
    Messages : 47
    Points : 30
    Points
    30
    Par défaut
    Je pensais à une solution sur la boucle de lecture de mon fichier.txt...

    pour qu'effectivement la lecture de ligne suivante dans le main soit déclenchée une fois que le thread a fini le téléchargement du premier fichier. Mais je vais geler l'UI je pense non?

    donc ce que tu me proposes c'est de transformer mon fichier.txt en arraylist puis de la gérer dans le thread de téléchargement?

    En fait je destine ce code à une petite appli android...le téléchargement est géré par la classe DownloadManager qui télécharge en tache de fond.

    Mais je veux que les fichiers soient téléchargés un par un...et pas mis en queue par DownloadManager, car je veux afficher une barre de progression pour chaque fichier..

    Je ne sais pas si c'est très clair

    Tu l'as compris..je débute!

    Nota : je ne cherche pas à attendre 2s entre chaque téléchargement..à la place du sleep il y un lancement de téléchargement avec le fameux DownloadManager d'android..

  6. #6
    Modérateur
    Avatar de joel.drigo
    Homme Profil pro
    Ingénieur R&D - Développeur Java
    Inscrit en
    Septembre 2009
    Messages
    12 430
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 54
    Localisation : France, Paris (Île de France)

    Informations professionnelles :
    Activité : Ingénieur R&D - Développeur Java
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Septembre 2009
    Messages : 12 430
    Points : 29 131
    Points
    29 131
    Billets dans le blog
    2
    Par défaut
    Citation Envoyé par aristide13 Voir le message
    pour qu'effectivement la lecture de ligne suivante dans le main soit déclenchée une fois que le thread a fini le téléchargement du premier fichier. Mais je vais geler l'UI je pense non?
    Sauf si tu fais tout le code (donc lecture du fichier de nom, et téléchargements) dans le même thread (qui n'est pas celui d'origine).

    Citation Envoyé par aristide13 Voir le message
    donc ce que tu me proposes c'est de transformer mon fichier.txt en arraylist puis de la gérer dans le thread de téléchargement?
    C'est une solution. Moi je parlais de construire une liste partagée entre les 2 threads, dans un modèle producteur-consommateur.

    Citation Envoyé par aristide13 Voir le message
    En fait je destine ce code à une petite appli android...le téléchargement est géré par la classe DownloadManager qui télécharge en tache de fond.
    Pour la programmation d'application android, je n'y connais rien : donc je ne sais pas du tout comment fonctionne le DownloadManager.

    Citation Envoyé par aristide13 Voir le message
    Mais je veux que les fichiers soient téléchargés un par un...et pas mis en queue dans par DownloadManager car je veux afficher une barre de progression pour chaque fichier.
    En gros, tu veux qu'une action de GUI lance un téléchargement de plusieurs fichiers, dont les noms sont dans un fichier d'entrée, les uns après les autres, en mettant à jour la GUI après chaque chargement (la barre de progression) et sans bloquer la GUI : un SwingWorker serait indiqué (même si tu peux le faire avec un thread).

    Pour moi, le plus simple est de lire tous les noms d'abord et de les stocker dans une liste, que tu traites après, tout ça dans le thread du SwingWorker. Sauf si le fichier d'entrée est énorme, auquel cas, ça va prendre du temps à le charger avant de télécharger le premier fichier, et de la mémoire pour stocker tous les noms.

    Si tu veux réaliser un système qui lit les noms les uns après les autres, pour lancer un thread de téléchargement successivement pour chaque fichier, comme tu as essayé de faire, au lieu d'utiliser un boolean startNext, utilise un simple objet et les méthodes wait et notify.

    Le principe est de créer une instance d'Object (peu importe la classe, on veux juste une référence unique) et que cette instance soit partagée entre les deux threads. La méthode wait() permet de mettre le thread qui l'appelle en attente. La méthode notifyAll() permet de débloquer les threads qui sont en attente.

    Par exemple (je reprends tes exemples) :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    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
    51
    52
    53
    54
    55
    56
    57
    58
    59
    60
    61
    62
    public class Example {
     
         ...
     
         private final static Object SYNC = new Object();
     
         public static void main(String args[]) throws FileNotFoundException {
             ...
         }
     
     
         public static void telecharger (  final String fichiersATelecharger ){
     
    	// on supprime startNext = false;
     
    	synchronized(SYNC) {
     
    	   new Thread(new Runnable() {
     
    		// ne sert à rien public boolean startNext ;
     
                 @Override
                 public void run() {
            	// ??? Example.fichiersATelecharger = fichiersATelecharger;
     
            	System.out.print(fichiersATelecharger);
            	System.out.print("\n");
            	//simulation du temps de téléchargement
            	try { 
            	    Thread.sleep(2000);
            	}
            	catch (InterruptedException exception) {
            	     exception.printStackTrace();
            	}
     
            	//setStartNext(true);
     
                    // le téléchargement est terminé, on indique que le thread qui attend peur recommencer à lire le prochain nom : le mettre éventuellement mettre un finally d'un try sur le téléchargement, pour que même en cas d'exception, ce code soit bien appelé
                    synchronized(SYNC) {
    	           SYNC.notifyAll(); // indiquer aux threads en attente qu'il peuvent reprendre
    	        }
     
               }
     
    		/* à supprimer public void setStartNext(boolean startNext) {
    		}*/
    	}).start();
     
                try {
    	       SYNC.wait(); // le thread courant est mis en attente (voir la méthode wait(int) pour gérer un timeout (et vérifier alors ou en est le téléchargement (planté, en cours, etc...)
                } catch(InterruptedException e) {
                    // traiter ici le cas d'arrêt du programme en cours d'attente de façon adéquate 
                   // par exemple, en retournant un boolean qui indique à la boucle appelant qu'elle ne pas continuer à lire les prochains noms et fermer le fichier qu'on est entrain de lire
     	   }
     
           }
     
    }
     
    }     
     
    }
    L'expression "ça marche pas" ne veut rien dire. Indiquez l'erreur, et/ou les comportements attendus et obtenus, et donnez un Exemple Complet Minimal qui permet de reproduire le problème.
    La plupart des réponses à vos questions sont déjà dans les FAQs ou les Tutoriels, ou peut-être dans une autre discussion : utilisez la recherche interne.
    Des questions sur Java : consultez le Forum Java. Des questions sur l'EDI Eclipse ou la plateforme Eclipse RCP : consultez le Forum Eclipse.
    Une question correctement posée et rédigée et vous aurez plus de chances de réponses adaptées et rapides.
    N'oubliez pas de mettre vos extraits de code entre balises CODE (Voir Mode d'emploi de l'éditeur de messages).
    Nouveau sur le forum ? Consultez Les Règles du Club.

  7. #7
    Nouveau membre du Club
    Homme Profil pro
    artisan
    Inscrit en
    Octobre 2013
    Messages
    47
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Bouches du Rhône (Provence Alpes Côte d'Azur)

    Informations professionnelles :
    Activité : artisan
    Secteur : Bâtiment

    Informations forums :
    Inscription : Octobre 2013
    Messages : 47
    Points : 30
    Points
    30
    Par défaut
    Avant toute chose merci beaucoup pour ta réponse et ton temps!

    Je vais essayer de mettre en oeuvre ta solution appliquée à mon petit projet...

    Je débute en java...et j'ai une vision d'un flux linéaire de code. Donc la notion de thread est encore trouble pour moi!

    Je reviendrai te faire part de mon avancement, mais à coup sur je vais encore un peu progresser aujourd'hui!

    Encore merci!

Discussions similaires

  1. Problème avec un thread (débutant en thread)?
    Par Jayceblaster dans le forum C#
    Réponses: 10
    Dernier message: 17/01/2007, 11h01
  2. Problèmes avec les thread et les pointeurs
    Par raspac dans le forum POSIX
    Réponses: 2
    Dernier message: 22/10/2006, 17h35
  3. [BOOST] Problème avec les threads
    Par SOAD08 dans le forum Dev-C++
    Réponses: 7
    Dernier message: 08/10/2006, 10h23
  4. Réponses: 1
    Dernier message: 08/08/2006, 15h39
  5. Réponses: 5
    Dernier message: 10/05/2005, 10h22

Partager

Partager
  • Envoyer la discussion sur Viadeo
  • Envoyer la discussion sur Twitter
  • Envoyer la discussion sur Google
  • Envoyer la discussion sur Facebook
  • Envoyer la discussion sur Digg
  • Envoyer la discussion sur Delicious
  • Envoyer la discussion sur MySpace
  • Envoyer la discussion sur Yahoo