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

Concurrence et multi-thread Java Discussion :

[Thread] Un père qui doit attendre la fin des fils


Sujet :

Concurrence et multi-thread Java

  1. #1
    Membre averti Avatar de Chatbour
    Profil pro
    Étudiant
    Inscrit en
    Septembre 2006
    Messages
    431
    Détails du profil
    Informations personnelles :
    Localisation : Tunisie

    Informations professionnelles :
    Activité : Étudiant

    Informations forums :
    Inscription : Septembre 2006
    Messages : 431
    Points : 305
    Points
    305
    Par défaut [Thread] Un père qui doit attendre la fin des fils
    Salut à tous et à toutes

    j'essaye de synchroniser un groupe de thread (classe MyThread) pour obtenir le fonctionnement suivant :
    le thread principal crée 5 thread qui affichent un simple message, puis affiche à son tour un message..
    j'insiste sur le fait que le message du thread principal doit s'afficher le dernier..

    voilà le code de la classe MyThread :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    class MyThread extends Thread {
        private int i;
     
        public MyThread(int i) {
            this.i = i;
        }
     
        @Override
        public void run() {
            System.out.println("je suis thread " + i);
        }
    }
    le code de la classe principale :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    public class Test {
        public static void main() {
            for (int i=0; i<5; i++) {
                Thread thread = new MyThread(i);
                thread.start();
            }
            System.out.println("et enfin moi");
        }
    }
    Le problème que je ne peux pas utiliser les méthodes wait() et notify() pour assurer le fonctionnement souhaité, du fait qu'un thread ne peut pas "notifier" son père..

    Merci d'avance pour vos idées..

  2. #2
    Invité
    Invité(e)
    Par défaut
    Salut,
    Est-ce que la méthode Thread.join pourrait répondre à tes attentes ?
    Tschau

  3. #3
    Membre actif Avatar de Balbuzard
    Profil pro
    Inscrit en
    Août 2008
    Messages
    381
    Détails du profil
    Informations personnelles :
    Âge : 38
    Localisation : France

    Informations forums :
    Inscription : Août 2008
    Messages : 381
    Points : 263
    Points
    263
    Par défaut
    ou alors, tu peux essayer de contourner le problème en faisant incrémenter chacun de tes Threads une variable, et mettre une condition pour l'affichage du dernier message : le fait que la variable en question ait atteint une certaine valeur (qui correspond au nombre de Threads)

    Bon, c'est peut-être pas de cette façon-là que tu souhaites résoudre ton problème...

    EDIT: peut-être une autre façon de faire :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    for(int i=0; i<nbreThread; i++) {
    if(thread.getState()=="TERMINATED") {
    condition++;
    }
    }
    if(condition==nbreThread) {
    System.out.println(dernierMessage);
    }
    ZORRO
    Plus Vengeur que Masqué

  4. #4
    Membre éclairé
    Profil pro
    Inscrit en
    Juillet 2007
    Messages
    802
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Juillet 2007
    Messages : 802
    Points : 653
    Points
    653
    Par défaut
    Tu peux utiliser un CountDownLatch :
    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
     
    class MyThread extends Thread {
    	private CountDownLatch countdown;
    	private int i;
     
    	public MyThread(int i, CountDownLatch countdown) {
    		this.i = i;
    		this.countdown = countdown;
    	}
     
    	@Override
    	public void run() {
    		System.out.println("je suis thread " + i);
    		countdown.countDown();
    	}
    }
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
     
    public class Test {
    	public static void main() {
    		CountDownLatch countdown = new CountDownLatch(5);
    		for (int i=0; i<5; i++) {
    			Thread thread = new MyThread(i, countdown);
    			thread.start();
    		}
    		countdown.await();
    		System.out.println("et enfin moi");
    	}
    }

  5. #5
    Expert éminent sénior
    Avatar de adiGuba
    Homme Profil pro
    Développeur Java/Web
    Inscrit en
    Avril 2002
    Messages
    13 938
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France

    Informations professionnelles :
    Activité : Développeur Java/Web
    Secteur : Transports

    Informations forums :
    Inscription : Avril 2002
    Messages : 13 938
    Points : 23 190
    Points
    23 190
    Billets dans le blog
    1
    Par défaut
    Salut,

    Balbuzard > Ta solution n'est pas bonne car il faut synchronisé tout cela


    Sinon une autre solution serait d'utiliser les Executors de Java 5 :
    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
    class MyTask implements Callable<Integer> {
        private int i;
     
        public MyTask(int i) {
            this.i = i;
        }
     
        @Override
        public Integer call() throws Exception {
        	System.out.println("je suis thread " + i);
        	return i;
        }
    }
     
    public class Test {
        public static void main() throws Exception {
        	// On crée une liste de tâche :
        	List<MyTask> tasks = new ArrayList<MyTask>();
            for (int i=0; i<5; i++) {
            	tasks.add(new MyTask(i));
            }
            // On crée un ExecutorService qui executera au plus 2 tâche à la fois :
            ExecutorService executor = Executors.newFixedThreadPool(2);
            // On lance l'exécution de toutes les tâches (et on attend qu'elles soient finies)
            List<Future<Integer>> results = executor.invokeAll(tasks);
            System.out.println("et enfin moi");
        }
    }
    a++

  6. #6
    Membre averti Avatar de Chatbour
    Profil pro
    Étudiant
    Inscrit en
    Septembre 2006
    Messages
    431
    Détails du profil
    Informations personnelles :
    Localisation : Tunisie

    Informations professionnelles :
    Activité : Étudiant

    Informations forums :
    Inscription : Septembre 2006
    Messages : 431
    Points : 305
    Points
    305
    Par défaut
    Re,

    merci beaucoup pour vos réponses

    je vais adopter une des solutions de adiGuba ou de verbose..

    George7 -> la raison que je n'ai pas utilisé la méthode join() c'est parce qu'en l'utilisant je vais perdre le parallélisme car tous les thread vont s'exécuter séquentiellement..

    Bonne journée..

  7. #7
    Modérateur
    Avatar de OButterlin
    Homme Profil pro
    Inscrit en
    Novembre 2006
    Messages
    7 310
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France

    Informations forums :
    Inscription : Novembre 2006
    Messages : 7 310
    Points : 9 522
    Points
    9 522
    Billets dans le blog
    1
    Par défaut
    Citation Envoyé par adiGuba Voir le message
    ...
    Sinon une autre solution serait d'utiliser les Executors de Java 5 :
    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
    class MyTask implements Callable<Integer> {
        private int i;
     
        public MyTask(int i) {
            this.i = i;
        }
     
        @Override
        public Integer call() throws Exception {
            System.out.println("je suis thread " + i);
            return i;
        }
    }
     
    public class Test {
        public static void main() throws Exception {
            // On crée une liste de tâche :
            List<MyTask> tasks = new ArrayList<MyTask>();
            for (int i=0; i<5; i++) {
                tasks.add(new MyTask(i));
            }
            // On crée un ExecutorService qui executera au plus 2 tâche à la fois :
            ExecutorService executor = Executors.newFixedThreadPool(2);
            // On lance l'exécution de toutes les tâches (et on attend qu'elles soient finies)
            List<Future<Integer>> results = executor.invokeAll(tasks);
            System.out.println("et enfin moi");
        }
    }
    a++
    J'ai testé ton code (merci en passant, je ne connaissait pas ExecutorService and Cie) et à l'exécution, voici ce qu'il renvoie
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
     
    je suis thread 1
    je suis thread 2
    je suis thread 3
    je suis thread 4
    je suis thread 0
    et enfin moi
    Je suis surpris par l'ordre, je m'attendais à
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
     
    je suis thread 0
    je suis thread 1
    je suis thread 2
    je suis thread 3
    je suis thread 4
    et enfin moi
    Ça vient de quoi ?
    N'oubliez pas de consulter les FAQ Java et les cours et tutoriels Java

  8. #8
    Membre averti Avatar de Chatbour
    Profil pro
    Étudiant
    Inscrit en
    Septembre 2006
    Messages
    431
    Détails du profil
    Informations personnelles :
    Localisation : Tunisie

    Informations professionnelles :
    Activité : Étudiant

    Informations forums :
    Inscription : Septembre 2006
    Messages : 431
    Points : 305
    Points
    305
    Par défaut
    adiGuba -> j'ai essayé ta solution, ça marche nickel mais je remarque que le programme reste bloqué à la fin et ne rend pas la main

  9. #9
    Expert éminent sénior
    Avatar de adiGuba
    Homme Profil pro
    Développeur Java/Web
    Inscrit en
    Avril 2002
    Messages
    13 938
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France

    Informations professionnelles :
    Activité : Développeur Java/Web
    Secteur : Transports

    Informations forums :
    Inscription : Avril 2002
    Messages : 13 938
    Points : 23 190
    Points
    23 190
    Billets dans le blog
    1
    Par défaut
    Citation Envoyé par Chatbour Voir le message
    George7 -> la raison que je n'ai pas utilisé la méthode join() c'est parce qu'en l'utilisant je vais perdre le parallélisme car tous les thread vont s'exécuter séquentiellement..
    join() est bien une solution valable, mais il faut bien sûr les effectuer après avoir lancé tous les threads. Il faut donc faire une liste de thread :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
        	List<Thread> threads = new ArrayList<Thread>();
            for (int i=0; i<5; i++) {
                Thread thread = new MyThread(i);
                thread.start();
                threads.add(thread);
            }
            for (Thread thread : threads) {
            	thread.join();
            }
            System.out.println("et enfin moi");
    Citation Envoyé par OButterlin Voir le message
    Je suis surpris par l'ordre
    Les threads sont exécutés en parallèle : tu ne peux pas déterminer de façons sûr l'ordre exact dans lequel ils s'exécuteront...

    Citation Envoyé par Chatbour Voir le message
    adiGuba -> j'ai essayé ta solution, ça marche nickel mais je remarque que le programme reste bloqué à la fin et ne rend pas la main
    Oui j'ai oublié un petit détail : après la fin de tous les traitements, les exécutors conservent les threads endormis afin de pouvoir les réutiliser par la suite, afin de pouvoir les réutiliser sans avoir à recréer un nouveau thread auprès du système.

    Donc comme il y a toujours des threads "vivants" ton programme ne s'arrête pas.


    Il y a deux solutions :
    1. Spécifier une ThreadFactory pour utiliser des threads daemon :
      Code : Sélectionner tout - Visualiser dans une fenêtre à part
      1
      2
      3
      4
      5
      6
      7
      8
              ExecutorService executor = Executors.newFixedThreadPool(2, new ThreadFactory() {
              	@Override
              	public Thread newThread(Runnable r) {
              		Thread thread = new Thread(r);
              		thread.setDaemon(true);
              		return thread;
              	}
              });
      Les threads daemon ne sont pas compter dans la liste des threads "vivants". C'est à dire que lorsqu'il ne reste que des threads daemon en vie, ils seront stoppé et le programme s'arrêtera...

    2. Arrêter l'executor, ce qui tuera tous les threads une fois que les actions en cours seront terminées (dans le cas où on aurait utiliser submit()). Il suffit pour cela d'appeler la méthode shutdown() après avoir exécuté nos tâches :
      Note : on ne pourra plus utilisé l'exécutor par la suite...


    a++

  10. #10
    Membre averti Avatar de Chatbour
    Profil pro
    Étudiant
    Inscrit en
    Septembre 2006
    Messages
    431
    Détails du profil
    Informations personnelles :
    Localisation : Tunisie

    Informations professionnelles :
    Activité : Étudiant

    Informations forums :
    Inscription : Septembre 2006
    Messages : 431
    Points : 305
    Points
    305
    Par défaut
    Merci bien adiGuba pour toutes ces explications

+ Répondre à la discussion
Cette discussion est résolue.

Discussions similaires

  1. [Multi thread] Attendre la fin des threads
    Par rvzip64 dans le forum Langage
    Réponses: 4
    Dernier message: 12/05/2015, 10h53
  2. Réponses: 7
    Dernier message: 21/02/2014, 20h55
  3. Attendre la fin des animations sur un groupe
    Par SpaceFrog dans le forum jQuery
    Réponses: 13
    Dernier message: 19/03/2011, 22h49
  4. Attendre la fin des threads fils d'un processus
    Par SteelBox dans le forum Windows
    Réponses: 15
    Dernier message: 24/02/2006, 16h08
  5. [Thread] comment attendre la fin d'un thread?
    Par billynirvana dans le forum Concurrence et multi-thread
    Réponses: 11
    Dernier message: 24/08/2005, 10h43

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