CONNEXION
  • RetourJeux
    • Sorties
    • Hit Parade
    • Les + populaires
    • Les + attendus
    • Soluces
    • Tous les Jeux
    • Gaming
  • RetourActu Gaming
    • News
    • Astuces
    • Tests
    • Previews
    • Toute l'actu gaming
  • RetourBons plans
    • Bons plans
    • Bons plans Smartphone
    • Bons plans Hardware
    • Bons plans Image et Son
    • Bons plans Amazon
    • Bons plans Cdiscount
    • Bons plans Decathlon
    • Bons plans Fnac
    • Tous les Bons plans
  • RetourJVTech
    • Actus High-Tech
    • Intelligence Artificielle
    • Smartphones
    • Mobilité urbaine
    • Hardware
    • Image et son
    • Tutoriels
    • Tests produits High-Tech
    • Guides d'achat High-Tech
    • JVTech
  • RetourCulture
    • Actus Culture
    • Culture
  • RetourVidéos
    • A la une
    • Gaming Live
    • Vidéos Tests
    • Vidéos Previews
    • Gameplay
    • Trailers
    • Chroniques
    • Replay Web TV
    • Toutes les vidéos
  • RetourForums
    • Hardware PC
    • PS5
    • Switch 2
    • Xbox Series
    • Switch
    • Pokemon pocket
    • FC 25 Ultimate Team
    • League of Legends
    • Tous les Forums
  • PC
  • PS5
  • Xbox Series
  • Switch 2
  • PS4
  • One
  • Switch
  • iOS
  • Android
  • MMO
  • RPG
  • FPS
En ce moment Genshin Impact Valhalla Breath of the wild Animal Crossing GTA 5 Red dead 2
Liste des sujets

[Java] réveiller un thread

iscario
iscario
Niveau 7
25 décembre 2009 à 17:26:36

Bonjour,

Je débute sur les threads en java, et j'ai un problème :-)
J'essaye de mettre en attente et de réveiller un thread par le biais des wait() et notify() voir notifyAll(), mais je n'y arrive pas :(

Voici le code au niveau du thread qui appelle (notify) :

j'ai une variable qui pointe sur le thread à réveiller, et une variable sur laquelle je veux agir pour faire des ajouts ou des suppressions lors de l'appel:

public Nettoyeur net;
public ArrayList ens;

et dans le code, pour appeler le thread en question (lors du finally) :

finally {
try {
synchronized (this.ens) {
net.notifyAll();
}

} catch (IOException ioe) {
ioe.printStackTrace();
}
}

Pour la classe qui se fait réveiller, voila le code :

http://pastebin.com/m1da95de2

Il y a certainement quelquechose que je n'ai pas compris, mais je ne sais pas quoi....

merci à vous

godrik
godrik
Niveau 30
26 décembre 2009 à 03:02:21

qu'est ce que tu veux dire par "je n'y arrive pas" ?
ca ne compile pas ?
ca ne fait pas ce que tu veux ?
Quel comportement attends tu ? Quel comportement constates tu ?

_skip
_skip
Niveau 10
26 décembre 2009 à 10:43:01

Il semble que tu ne maîtrise pas vraiment les outils de synchronisation, à voir ton code...

Tu as rendu la méthode run synchronized, à quoi bon? C'est la méthode principale du Thread, t'as pas prévu qu'un autre code que celui de la méthode start() du Thread puisse l'appeler? (d'ailleurs, pour commencer, est-ce que tu appelles cette méthode start?)

En plus derrière tu fais un synchronized(this), ce qui oblige le thread à réacquérir un verrou qu'il possède déjà (réentrance insensée), et tu as ensuite la méthode wait() qui lâche le verrou sur "this".

En fait tu dois toujours te poser la question suivante avant de mettre du code de synchronisation partout, quels objets sont partagés entre les threads et quels sont les dangers si quelqu'un les modifie? Ici, c'est clairement l'ArrayList qui est vulnérable.

La section critique de ton code c'est le parcours de la liste (le for). Or cette liste tu la passes par le constructeur, donc un autre objet que ton thread possède une référence externe sur l'arrayList, si il fait un add() ou un remove() pendant que le Thread exécute la boucle for(), dans le meilleur des cas tu auras une exception parce que l'itérateur est fail-fast, dans le pire des cas ça marchera et c'est ailleurs que ça pétera.

Même si je sais pas bien ce que tu essaies de faire, je te propose d'essayer avec une autre philosophie :

class Thread
{
private ArrayList cleanupList;

public void synchronized addConnectionToCleanupList(); //appelée de l'extérieur
public void run();
private void synchronized cleanupCurrentList(); //appelée par run le moment venu

}

Comme ça tu controles entièrement le réveil du thread de l'intérieur, moins de code spaghetti et c'est beaucoup plus sûr.

iscario
iscario
Niveau 7
29 décembre 2009 à 14:07:20

Je reviens là-dessus :d)
"La section critique de ton code c'est le parcours de la liste (le for). Or cette liste tu la passes par le constructeur, donc un autre objet que ton thread possède une référence externe sur l'arrayList, si il fait un add() ou un remove() pendant que le Thread exécute la boucle for(), dans le meilleur des cas tu auras une exception parce que l'itérateur est fail-fast, dans le pire des cas ça marchera et c'est ailleurs que ça pétera. "

Je pensais justement que l'utilisation des synchronized aux bons endroits permettraient de ne pas avoir de problème : c'est juste ou pas ?

sinon ce que je fais c'est un chat client-serveur en java , et mon problème intervient pour gérer les déconnections des clients coté serveurs (quand un client se déconnecte, je veux le supprimer du tableau.)

voici toutes les classes que j'utilise pour le serveur :
http://pastebin.com/m7156e550
http://pastebin.com/m73be5a42
http://pastebin.com/m3fa8eca1

je pensais qu'avec ces synchronized, ca devrait etre bon. Néanmoins ca coince toujours : quand je lance 3 clients, que je fais une déconnection, j'obtiens l'erreur suivante dans la console :

run:
il y a 1 client(s) connecté(s)
il y a 2 client(s) connecté(s)
il y a 3 client(s) connecté(s)
Exception in thread "Thread-0" java.util.ConcurrentModificationException
delClient()
at
java.util.AbstractList$Itr.checkForComodification(
AbstractList.java:372)
at
java.util.AbstractList$Itr.next(AbstractList.java:
343)
at appliserveur.Nettoyeur.run(Nettoyeur.java:28)

Si je suis les conseils indiqués, je doit traiter un seul arrayList dans une seule classe, mais cela me semble difficile car l'intéret c'est qu'un thread le fasse en // il me semble. non ?

_skip
_skip
Niveau 10
30 décembre 2009 à 13:40:56

Si tu laisses un objet critique être accédé hors de la classe qui le manipule, tu as aucune sécurité autre que de prier pour que ce code qui est à l'extérieur respecte le principe de la synchronisation.

C'est une bombe à retardement, le bon fonctionnement d'une classe ne devrait jamais dépendre ainsi de ce qui se passe à l'extérieur.

Mais dans un premier temps, il faut que tu comprennes ce qui se passe avec synchronized en faisant des exemples plus simples.

Tu peux par exemple commencer avec :
http://rom.developpez.com/java-synchronisation/

Sinon si tu maîtrises l'anglais il y a d'excellentes ressources dans cette langue sur le sujet.

Sous forums
  • Aide à l'achat Mac
  • Création de sites web
  • Création de Jeux
  • Linux
  • Programmation
  • Internet
  • Steam Deck
  • Macintosh
  • Hardware
La vidéo du moment