Threads synchronisés ?

Threads synchronisés ? - Java - Programmation

Marsh Posté le 02-12-2009 à 14:08:47    

Hello
Voilà j'essaie de faire un programme avec 2 threads et j'ai beaucoup de mal à comprendre comment les faire communiquer.
 
En gros j'ai un thread 1 de calcul dont la méthode run() consiste a calculer un tableau et à la stocker quelque part. L'opération prend en gros 10 ms.
 
En parralèle j'ai un thread 2 d'affichage qui se charge d'afficher les données d'un tableau toutes les 10 ms et qui le fait 10 fois avant de le faire sur le tableau suivant. L'opération sur un tableau donné me prend donc 100 ms.
 
Bref je voudrais que mon thread 1 se bloque quand il a fini de calculer, et que le thread 2 puisse le relancer quand l'affichage est fini (itération d'apres)
De meme, il faudrait que le thread 2 puisse se bloquer et attendre que le thread 1 ait fini de calculer dans le cas rare où le thread 1 aurait été lent.
 
 
Je ne vois pas trop comment faire ça avec wait() et notifyAll() vu qu'il faut des méthodes synchronisées. Bref comment bloquer et relancer un thread depuis un autre ?

Reply

Marsh Posté le 02-12-2009 à 14:08:47   

Reply

Marsh Posté le 02-12-2009 à 14:19:30    

quand dans un thread tu fais un wait() sur un objet, ça bloque le thread.
Pour le débloquer, il faut qu'un autre thread fasse un notify() sur le même objet.


---------------
ma vie, mon oeuvre - HomePlayer
Reply

Marsh Posté le 02-12-2009 à 14:21:15    

Ok donc je peux créer un objet inutile qui possède une méthode avec juste wait et une juste avec notify et que chaque thread appelle ?

Reply

Marsh Posté le 02-12-2009 à 14:24:06    

lezebulon20001 a écrit :

Ok donc je peux créer un objet inutile qui possède une méthode avec juste wait et une juste avec notify et que chaque thread appelle ?


même pas besoin de créer une nouvelle classe : tu peux te servir de n'importe quel object (ex : un object de type Object), mais ça marcherait avec n'importe quoi d'autre ....).
 

Code :
  1. public static final Object lock = new Object();
  2. //...
  3. lock.wait();
  4. //...
  5. lock.notify()


---------------
ma vie, mon oeuvre - HomePlayer
Reply

Marsh Posté le 02-12-2009 à 14:25:42    

Ah oui effectivement vu comme ça c'est assez simple :D Merci

Reply

Marsh Posté le 02-12-2009 à 14:53:05    

Je suggère plutôt d'éviter ces conneries moches bas niveau et de faire communiquer les threads via les queues fournies par java.util.concurrent.


---------------
Stick a parrot in a Call of Duty lobby, and you're gonna get a racist parrot. — Cody
Reply

Marsh Posté le 02-12-2009 à 15:23:30    

Ca change quelque chose niveau perf ? Vu que je compte avoir 2 locks au grand max je me vois mal faire un truc super gore

Reply

Marsh Posté le 02-12-2009 à 16:07:59    

lezebulon20001 a écrit :

Ca change quelque chose niveau perf ? Vu que je compte avoir 2 locks au grand max je me vois mal faire un truc super gore


Pas spécialement, ça simplifie le code et ça réduit les chances de faire des conneries.


---------------
Stick a parrot in a Call of Duty lobby, and you're gonna get a racist parrot. — Cody
Reply

Marsh Posté le 02-12-2009 à 17:11:01    

Bon apres testage ça marche pas... je me prend un IllegalMonitorStateException.
Ce que j'ai fait :
- mettre public static final Object lock = new Object(); dans la classe qui contient le main
- appeller lock.wait() ou lock.notifyAll() depuis mes threads créés depuis le main.
 
Comment corriger ça ?

Reply

Marsh Posté le 02-12-2009 à 20:02:01    

pas d'idée ?

Reply

Marsh Posté le 02-12-2009 à 20:02:01   

Reply

Marsh Posté le 03-12-2009 à 00:07:20    

Le thread qui doit faire l'affichage est l'EDT de Swing et on ne peut jamais le bloquer. C'est mal.
 
Le mieux est que tu utilises une instance de SwingWorker qui te crée un thread de travail, et qui te permet de poster des notifications de mise à jour de l'affichage à intervalles réguliers après X cycles de calcul complets, qui vont être traitées dans l'EDT. Lis bien la doc de la classe. Tu dois poster la notification via la méthode process() et tu lui passes en paramètre une copie de la matrice actuellement traitée (une nouvelle instance, pas celle que le thread de calcul utilise en parallèle).


Message édité par cbeyls le 03-12-2009 à 00:45:43
Reply

Marsh Posté le 03-12-2009 à 00:42:26    

Donc je résume:
 
Tu utilises un SwingWorker<Matrice,List<Matrice>>. Pour cela tu dois overrider différentes méthodes de celui-ci:
- tu overrides doInBackground() avec une méthode contenant l'ensemble travail de calcul sur les matrices, renvoyant tout à la fin une liste de matrices calculées.
Dans cette méthode, après chaque cycle complet de calcul sur une matrice, tu recopies la matrice dans une nouvelle instance et tu la passes en paramètre de publish() que tu appelles.
- tu overrides process() en mettant le code qui s'occupe de l'affichage. Il recevra une matrice en paramètre.
 
Ensuite tu lances ton SwingWorker en appelant execute().

Reply

Marsh Posté le 07-12-2009 à 21:15:25    

masklinn a écrit :

Je suggère plutôt d'éviter ces conneries moches bas niveau et de faire communiquer les threads via les queues fournies par java.util.concurrent.


[:mlc2] nan mais n'importe quoi ...
 
d'où t'as vu que wait et notify étaient des trucs bas niveaux ... par rapport à ce qu'il doit faire le monsieur, y a rien de plus simple/immédiat.


---------------
ma vie, mon oeuvre - HomePlayer
Reply

Marsh Posté le 09-12-2009 à 00:33:41    

Mais ses threads ne doivent pas attendre, il veut juste afficher la progression d'un calcul en cours. Surtout qu'il ne faut jamais que le thread d'affichage, l'EDT, attende.

Reply

Sujets relatifs:

Leave a Replay

Make sure you enter the(*)required information where indicate.HTML code is not allowed