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

Langage Java Discussion :

synchronisaton des thread


Sujet :

Langage Java

  1. #1
    nabila.abdessaied
    Invité(e)
    Par défaut
    salut,
    je veux implémenter ça
    une classe qui modélise un évènement appelé event
    cette classe implémente ces deux méthodes :waiting() and wakeup()
    nous avons juste un seul event et plusieurs thread qui partagent ce même évènement
    et on a un seul thread qui va notifier ces threads qui attendent
    il va faire wakeup de event alors tous les thread sortent de waiting

    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
    class a {
    public int a;=0;
    event e=new event();
    public a(){
    callThread(); //creation thread 1
    callThread(); //creation thread 2
    callThread(); //creation thread 3
    callThread(); //creation thread 4
    callThread(); //creation thread 5
    .
    .
    //nombre indefini de thread qui font le wait cad c pa statique on ne le sait pas
    .
    .
    //ce thread va notifier tous les autre thread
    new Thread (){
    run(){
    a=5;
    e.wakeup()
    }}.start();
    }
     
    //cette methode va creer un thread qui va attendre la notification de l//'evenement avant
    //et apres il va afficher le contenue de a
    private void callThread(){
    new Thread (){
    run(){
    e.waitng();
    System.out.println(a);
    }}.start();
    }
    normalement tous les thread ne vont pas afficher le contenu de a que après la notification
    mon problème c'est que dans cet exemple il y a un seul qui peut voir la notification
    et sort de la phase de d'attente
    parce que la notification fait le flag vaut true donc un seul tient compte de cette modification et sort de wait et modifient le flag a false donc les autres ne tiennent pas compte de cette modification et restent dans l'attente infinie
    voila la classe event

    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
    public final class Event {
    /**
    * variable used to store the notification if it takes place
    * before being expected
    */
    private boolean status = false;
     
    public final synchronized void waiting() {
    while (status == false ) {
    try {
    wait();
    }
    catch (InterruptedException e) {
    }
    }
    status = false ;
    }
    // notify all waits on this event
    public final synchronized void wakeUp() {
    status = true;
    notifyAll();
    }
     
     
    }
    après j'ai eu cette idée c'est de créer dans la classe event un tableau d'évènement
    si un thread veut entrer dans waiting il va créer un nouveau évènement et le store dans le tableau et ensuite il fait le wait sur cet évènement
    après si le thread de notification envoi la notification il va faire ce qui suit notifier tous les évènements de tableau
    mais il reste un souci
    c'est que on sait jamais si on fait tout les wait avant d'envoyer la notification
    par exemple si on a 60 thread qui vont entrer en wait
    il y a seulement 30 qui entrent
    après la notification aura lieu
    donc notification de tous les élément de tableau c'est à dire 30 thread seront notifiées et les autres même si il vont entrer après en wait il n'y a aucun thread qui va faire la notification
    donc si je sais pas le nombre de thread qui vont faire le wait
    comment je peux empêcher le thread qui envoie la notification d'envoyer la notification avant que tous les thread ont effectué les wait ?

    merci de me répondre
    Dernière modification par mlny84 ; 06/04/2009 à 09h44. Motif: syntaxe + SMS

  2. #2
    Membre habitué
    Profil pro
    Inscrit en
    Janvier 2007
    Messages
    121
    Détails du profil
    Informations personnelles :
    Localisation : Belgique

    Informations forums :
    Inscription : Janvier 2007
    Messages : 121
    Points : 136
    Points
    136
    Par défaut
    Si tu veux utiliser une variable status qui conditionne l'activation de chaque Thread ...alors tu dois mettre un status pour chaque Thread.
    Donc pas un seul dans Event.
    Ces ce status qui indique au Thread si il doit réagir à ce type évenement à ce moment.
    Si tu avait deux types d'évenements agissant sur chaque Thread tu aurais deux status (statusReactionAEvenement1 et statusReactionAEvenement2) modifiables par 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
    	public class MyRunnable implements Runnable {
    		private volatile boolean status = false;
     
    		public void run() {
    			waiting();
    			System.out.println(Thread.currentThread().getName()+"..."+a);
    		}
     
    		public final void waiting() {
    			while (status == false) {
    				try {
    					event.waitOnMySignal(this);
    				} catch (InterruptedException e) {
    				}
    			}
    			status=false;
    		}
     
    		public void setStatus(boolean status) {
    			this.status = status;
    		}
    	}
    Si tu veux réveiller tes Threads sachant qu'il attendent status==true , tu dois activer tous ces status avant d'appeler event.notifyAll(). Par exemple au niveau de ta classe Event comme suit...
    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
    public final class Event {
    		Set<MyRunnable> myRunnableSet=new HashSet<MyRunnable>();
     
    		// notify all waits on this event
    		public final synchronized void wakeUp() {
    			/*
    			 * Modififier le status de tous les Thread que Event doit activer
    			 */
    			for (MyRunnable myRunnable:myRunnableSet) {
    				myRunnable.setStatus(true);
    			}
    			myRunnableSet.clear();
     
    			System.out.println("WAKE UP AND SEE IF YOU STATUS WAS CHANGED BY ME...");
    			notifyAll(); // Notification à tous...
    		}
     
    		public final synchronized void waitOnMySignal(MyRunnable myRunnable) throws InterruptedException {
    			System.out.println(Thread.currentThread().getName()+"... IS NOW WAITING ON ME");
    			myRunnableSet.add(myRunnable);
    			wait(); // Dire au thread en cours d'attendre une notification de ma part
    		}
    	}
    Donc pas de liste d'évenements...
    apres j'ai eu cette idéé c de creer dans la classe event un tableau d'evenement
    ...Mais un Set ou une liste de Threads qui attendent une notification sur chaque évènement.

  3. #3
    Membre habitué
    Profil pro
    Inscrit en
    Janvier 2007
    Messages
    121
    Détails du profil
    Informations personnelles :
    Localisation : Belgique

    Informations forums :
    Inscription : Janvier 2007
    Messages : 121
    Points : 136
    Points
    136
    Par défaut
    Petit essai...
    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.util.HashSet;
    import java.util.Set;
     
    public class TestEventNotifyALL {
     
    	public final class Event {
    		Set<MyRunnable> myRunnableSet=new HashSet<MyRunnable>();
     
    		// notify all waits on this event
    		public final synchronized void wakeUp() {
    			/*
    			 * Modififier le status de tous les Thread que Event doit activer
    			 */
    			for (MyRunnable myRunnable:myRunnableSet) {
    				myRunnable.setStatus(true);
    			}
    			myRunnableSet.clear();
     
    			System.out.println("WAKE UP AND SEE IF YOUR STATUS WAS CHANGED BY ME...");
    			notifyAll(); // Notification à tous...
    		}
     
    		public final synchronized void waitOnMySignal(MyRunnable myRunnable) throws InterruptedException {
    			System.out.println(Thread.currentThread().getName()+"... IS NOW WAITING ON ME");
    			myRunnableSet.add(myRunnable);
    			wait(); // Dire au thread en cours d'attendre une notification de ma part
    		}
    	}
     
    	public int a = 0;
    	Event event = new Event();
     
    	public TestEventNotifyALL() {
     
    		callThread("T1"); // creation thread 1
    		callThread("T2"); // creation thread 2
    		callThread("T3"); // creation thread 3
    		callThread("T4"); // creation thread 4
    		callThread("T5"); // creation thread 5
     
    		// nombre indefini de thread qui font le wait cad c pa statique on ne le
    		// sait pas
     
    		// ce thread va notifier tous les autre thread
    		new Thread() {
    			public void run() {
    				a = 5;
    				event.wakeUp();
    			}
    		}.start();
    	}
     
    	public class MyRunnable implements Runnable {
    		private volatile boolean status = false;
     
    		public void run() {
    			waiting();
    			System.out.println(Thread.currentThread().getName()+"..."+a);
    		}
     
    		public final void waiting() {
    			while (status == false) {
    				try {
    					event.waitOnMySignal(this);
    				} catch (InterruptedException e) {
    				}
    			}
    			status=false;
    		}
     
    		public void setStatus(boolean status) {
    			this.status = status;
    		}
    	}
     
    	// cette methode va creer un thread qui va attendre la notification de
    	// l'evenement avant
    	// et apres il va afficher le contenue de a
    	private void callThread(final String name) {
    		Thread t=new Thread(new MyRunnable(),name);
    		t.start();
    	}
     
    	/**
             * @param args
             */
    	public static void main(String[] args) {
    		// TODO Auto-generated method stub
    		new TestEventNotifyALL();
    	}
     
    }
    Résultat...
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    T1... IS NOW WAITING ON ME
    T2... IS NOW WAITING ON ME
    T3... IS NOW WAITING ON ME
    T4... IS NOW WAITING ON ME
    T5... IS NOW WAITING ON ME
    WAKE UP AND SEE IF YOUR STATUS WAS CHANGED BY ME...
    T5...5
    T4...5
    T3...5
    T2...5
    T1...5

  4. #4
    nabila.abdessaied
    Invité(e)
    Par défaut
    si j'ajoute nombre d'itération ça marche pas tu peux voir le code ci-dessous
    il y a des notifications que les threads ne tiennent pas compte
    en plus j'ai pas compris pourquoi on efface le HashSet myRunnableSet avant de notifier
    et c'est quoi la différence entre hashSet et array list ?

    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
    93
    94
    95
    96
    97
    98
     
    import java.util.HashSet;
    import java.util.Set;
     
    public class TestEventNotifyALL {
     
        public final class Event {
            Set<MyRunnable> myRunnableSet=new HashSet<MyRunnable>();
     
            // notify all waits on this event
            public final synchronized void wakeUp() {
                /*
                
                 */
                for (MyRunnable myRunnable:myRunnableSet) {
                    myRunnable.setStatus(true);
                }
                myRunnableSet.clear();
                notifyAll(); 
                System.out.println("WAKE UP AND SEE IF YOUR STATUS WAS CHANGED BY ME...");
     
     
            }
     
            public final synchronized void waitOnMySignal(MyRunnable myRunnable) throws InterruptedException {
                //System.out.println(Thread.currentThread().getName()+"... IS NOW WAITING ON ME");
                myRunnableSet.add(myRunnable);
                wait(); // 
            }
        }
     
        public int a = 0;
        Event event = new Event();
     
        public TestEventNotifyALL() {
            new Thread() {
                public void run() {
                    for (int i = 0; i < 5; i += 1) {
                    a = i;
                    event.wakeUp();
                    try {
                        Thread.sleep(5);
                    } catch (InterruptedException e) {
                        // TODO Auto-generated catch block
                        e.printStackTrace();
                    }
                }
                }
            }.start();
            callThread("T1"); // creation thread 1
            callThread("T2"); // creation thread 2
            callThread("T3"); // creation thread 3
            callThread("T4"); // creation thread 4
            callThread("T5"); // creation thread 5
     
     
        }
     
        public class MyRunnable implements Runnable {
            private volatile boolean status = false;
     
            public void run() {
                for (int i = 0; i < 5; i += 1) {
                waiting();
                System.out.println(Thread.currentThread().getName()+"..."+a);
                }
            }
     
            public final void waiting() {
                while (status == false) {
                    try {
                        event.waitOnMySignal(this);
                    } catch (InterruptedException e) {
                    }
                }
                status=false;
            }
     
            public void setStatus(boolean status) {
                this.status = status;
            }
        }
     
     
        private void callThread(final String name) {
            Thread t=new Thread(new MyRunnable(),name);
            t.start();
        }
     
        /**
         * @param args
         */
        public static void main(String[] args) {
            // TODO Auto-generated method stub
            new TestEventNotifyALL();
        }
     
    }
    Dernière modification par mlny84 ; 06/04/2009 à 09h45. Motif: SMS

  5. #5
    Membre habitué
    Profil pro
    Inscrit en
    Janvier 2007
    Messages
    121
    Détails du profil
    Informations personnelles :
    Localisation : Belgique

    Informations forums :
    Inscription : Janvier 2007
    Messages : 121
    Points : 136
    Points
    136
    Par défaut
    Je pense voir ce que tu veux faire ...
    En y réfléchissant , on peu se passer de status puisque tes Threads sont tous réactifs par rapport à event. Donc la liste qui maintenais ces status à jour est inutile aussi...Event devient ...
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    public final class Event {
    		// notify all waits on this event
    		public final synchronized void wakeUp() {
    			System.out.println("WAKE UP AND SEE IF YOUR STATUS WAS CHANGED BY ME...");
    			notifyAll(); // Notification à tous...
    		}
     
    		public final synchronized void waitOnMySignal() throws InterruptedException {
    			System.out.println(Thread.currentThread().getName()+"... IS NOW WAITING ON ME");
    			wait(); // Dire au thread en cours d'attendre une notification de ma part
    		}
    	}
    Tes Threads passent la plus part de leur temps à attendre une notification de event...
    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
    	public class MyRunnable implements Runnable {
    		private volatile Event event=null;
     
    		public MyRunnable(Event event) {
    			this.event=event;
    		}
     
    		public void run() {
    			waiting();
    		}
     
    		public final void waiting() {	
    			while (event != null){
    				try {
    					event.waitOnMySignal();
    					synchronized (event) {
    						// !!! ICI tu dois faire quelque chose suite a l'évènement...
    						// Le "synchronized(event)" bloque les accès des autres Threads aux méthodes de event
    						// le temps de faire ce qui suit...
    						System.out.println(Thread.currentThread().getName()+"..."+a);
    					}
    				} catch (InterruptedException e) {
    					break;
    				}
    			}
    		}
     
    		public Event getEvent() {
    			return event;
    		}
     
    		public void setEvent(Event event) {
    			this.event = event;
    		}
    	}
    Ta boucle de notifications peu alors fonctionner comme suit...
    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
     
    public class TestEventNotifyALL {
     
    	public volatile int a = 0;
    	Event event = new Event();
     
    	public TestEventNotifyALL() {
    		/*
    		 * Threads T1 T2 T3 T4 T5
    		 */
    		for (int i = 1; i <= 5; i++) {
    			new Thread(new MyRunnable(event), "T" + i).start();
    		}
     
    		// Ce thread va notifier tous les autres thread
    		new Thread() {
    			public void run() {
    				for (int i = 0; i < 20; i++) {
    					a = i;
    					event.wakeUp();
    					/*
    					 * Attendre un peu...
    					 */
    					try {
    						Thread.sleep(5);
    					} catch (InterruptedException e) {
    						// TODO Auto-generated catch block
    						e.printStackTrace();
    					}
    				}
    			}
    		}.start();
    	}
     
    	/**
             * @param args
             */
    	public static void main(String[] args) {
    		// TODO Auto-generated method stub
    		new TestEventNotifyALL();
    	}
    }

  6. #6
    Membre habitué
    Profil pro
    Inscrit en
    Janvier 2007
    Messages
    121
    Détails du profil
    Informations personnelles :
    Localisation : Belgique

    Informations forums :
    Inscription : Janvier 2007
    Messages : 121
    Points : 136
    Points
    136
    Par défaut
    c quoi la difference entre hashSet et array list?
    Les "Set" (HashSet,LinkedHashSet,...) sont des collections d'objets référencés une seule X par objet. Une Liste (ArrayList,...) peu contenir plusieurs X la référence d'un même objet.
    si j'ajoute nombre d'itiration ça marche pas tu peux voir le code si dessous
    il ya des notification que les threads ne tiennent pas compte
    en plus j'ai pas compri pourkoi on efface le HashSet myRunnableSet avant de notifier
    Effectivement ce n'était pas une bonne solution (et de devoir réenregister à chaque fois les Threads réactifs sur ces évènements)...

Discussions similaires

  1. Réponses: 3
    Dernier message: 11/02/2004, 12h50
  2. Une question à propos des thread
    Par tscoops dans le forum C++Builder
    Réponses: 4
    Dernier message: 07/11/2003, 14h03
  3. Variable globale / Propriété des threads
    Par rgarnier dans le forum XMLRAD
    Réponses: 4
    Dernier message: 03/10/2003, 10h49
  4. [reseaux] Gestion des threads en perl
    Par totox17 dans le forum Programmation et administration système
    Réponses: 2
    Dernier message: 28/11/2002, 09h40
  5. Programmer des threads
    Par haypo dans le forum C
    Réponses: 6
    Dernier message: 02/07/2002, 13h53

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