OVH Cloud OVH Cloud

synchronisation de thread

6 réponses
Avatar
ted
Bonjour,

Je cherche a programmer le comportement suivant :

J'ai 4 threads T1 T2 T3 T4
mon Main lance T1.
T1 lance T2, puis attend ( dans T1 j'appelle la methode suivante:

public synchronized void attente() throws InterruptedException{
System.out.println("on va arreter le thread
"+Thread.currentThread().getName());
wait();
}

qui est defini dans Main )

T2 lance T3 et T4 ( T3 et T4 appellent attente() )

J'ai donc T1 T3 et T4 qui attendent.

Comment faire pour que T2 reveille seulement T1 ?

dans mon main j'ai declarer les fonctions suivantes :

public synchronized void relanceUn(){
notify();
}

public synchronized void relanceTous(){
notifyAll();
}

si j'appelle T2 execute relanceTous il relance tous les threads et si
j'appelle relanceUn il en relance 1 mais je ne suis pas sur qu'il
relance T1.

Il me faudrai donc une fonction ( avec un thread en param??) qui me
relance juste le thread d=E9sir=E9.
Est possible?

Merci de vos reponses.

Cordialement.

6 réponses

Avatar
ted
- soit disposer d'un objet clef spécifique au thread 1 ; le thread qui
voudra réveiller le thread 1 fera alors lockthread1.notify() ; cette
approche me parait plus correcte, parce qu'elle simplifie le code à la fois
du coté du réveilleur et du coté reveillé, et qu'elle matériali se dans un
seul objet clef la rythmique pour le thread 1 ; elle est beaucoup plus
robuste s'il y a par exemple plusieurs thread 1, 2, 3, 4... à reveiller ou
à endormir et que tout ça peut se paumer dans les subtilités des wa it et
notify.



merci de cette reponse.

Si j'ai bien compris, je vais declarer un tableau de thread dans mon
Main.
A chaque thread qui run, je mets sa reference dans le tableau.
Et ensuite je pourrai faire un _main.Tableau[ThreadVoulu].notify(); ?
J'ai un doute sur cette facon de proceder, ne risque t on pas de tomber
dans un ThreadNotOwner Exeception

merci.

Cordialement

Avatar
Hervé AGNOUX
ted wrote:


Il me faudrai donc une fonction ( avec un thread en param??) qui me
relance juste le thread désiré.
Est possible?



Il faut :

- soit disposer un flag qui dise "reveil pour le thread 1", flag que l'on
initialise juste avant le notify, et que chaque thread réveillé devra
tester à son réveil ; je n'aime pas beaucoup cette solution, parce qu'elle
complique la gestion de chaque thread,

- soit disposer d'un objet clef spécifique au thread 1 ; le thread qui
voudra réveiller le thread 1 fera alors lockthread1.notify() ; cette
approche me parait plus correcte, parce qu'elle simplifie le code à la fois
du coté du réveilleur et du coté reveillé, et qu'elle matérialise dans un
seul objet clef la rythmique pour le thread 1 ; elle est beaucoup plus
robuste s'il y a par exemple plusieurs thread 1, 2, 3, 4... à reveiller ou
à endormir et que tout ça peut se paumer dans les subtilités des wait et
notify.


--
Hervé AGNOUX
http://www.diaam-informatique.com

Avatar
Hervé AGNOUX
ted wrote:


Si j'ai bien compris, je vais declarer un tableau de thread dans mon
Main.
A chaque thread qui run, je mets sa reference dans le tableau.
Et ensuite je pourrai faire un _main.Tableau[ThreadVoulu].notify(); ?
J'ai un doute sur cette facon de proceder, ne risque t on pas de tomber
dans un ThreadNotOwner Exeception



Je ne connais pas l'ensemble de votre sujet, et notamment pas ce que
représente ces objets, threads etc dans le domaine que vous voulez
manipuler.

Donc je ne peux pas vous répondre si les tableaux sont les plus appropriés,
etc.

Pour ne pas avoir de ThreadNotOwnerException, il suffit de respecter le
principe habituel :

synchronized (_main.Tableau[ThreadVoulu])
{
_main.Tableau[ThreadVoulu].notify();
}

c'est le principe ; après, pour l'application, je ne sais pas :-)


--
Hervé AGNOUX
http://www.diaam-informatique.com

Avatar
ted
merci de la reponse ... voici mon code rajouté dans main:
HashMap m=new HashMap();

synchronized void addThread(Thread T){
m.put(T.getName(),T);
}

synchronized void notifyThread(String Tname){
m.get(Tname).notify();
}

synchronized void waitThread(String Tname) throws
InterruptedException{
m.get(Tname).wait();
}

mon main lance le 1er Thread T1.
T1 lance T2.
A chaque thread lancé j'appelle addThread(Thread T) pour rajouter le
Thread dans ma HashMap. c'est ok jusque la.
Mais si je souhaite faire attendre T1 ( appelle de
_m.waitThread(this.getName()); )
j'ai " java.lang.IllegalMonitorStateException: JVMLK008: current thread
not owner ".
Etrange, non ?
Avatar
Hervé AGNOUX
ted wrote:

Etrange, non ?


Mais non... l'objet de synchronisation doit être le même que celui de wait
ou notify.

Donc il faut faire des choses du genre :

void waitThread(String Tname) throws InterruptedException
{
Object lock;

lock = m_get(Tname);
synchronized (lock)
{
lock.wait();
}
}

A+.


--
Hervé AGNOUX
http://www.diaam-informatique.com

Avatar
ted
Mais non... l'objet de synchronisation doit être le même que celui de wait
ou notify.



Mais c'est bien sûr !
Merci en tout cas, effectivement c mieux !