Gestion d'évènements - Java - Programmation
Marsh Posté le 08-08-2002 à 11:02:35
Code :
|
Ensuite dans ton XXXServer (en gros l'objet qui dois générer des évenements, tu as un truc du genre
Code :
|
Ensuite dans la classe qui doit recevoir l'evenements tu lui fais implémenter XXXEventListener et lorsque tu l'instancies ou que tu la configures tu appelles addXXXEventListener(this) (ou l'objet qui implémentes le listener) sur le XXXServer dont tu veux recevoir des évenements.
Clair?
Marsh Posté le 08-08-2002 à 11:07:35
ici mon XXXEvent n'étends pas l'event générique et ca tu peux le faire si les méthodes incluses t'intéresse ...
Marsh Posté le 08-08-2002 à 11:19:48
histoire de rappeler le bon vieux temps ou je rajoutait toujours mon grain de sel à ce que disait dark, tu peux utiliser un Set pour stocker les listeners (genre java.util.HashSet) et t'assurer qu'ils soient uniques
et si je me trompe pas, il faut aussi que le addEvent listener soit synchronized sinon ca va planter si tu en ajoute un pendant qu'il est en train de balancer les évenements.
Marsh Posté le 08-08-2002 à 11:25:08
ah oui. C'est juste ca
merci pour l'info
Marsh Posté le 08-08-2002 à 11:55:48
ceci dit benou,
HashSet ne sert vraiment à rien parce que là seule méthode qui le remplit prend comme argument un XXXEventListener
synchronized n'est pas requis puisque la méthode qui génère les évenemtns est synchronisés sur l'objet. A moins qu'il y ait ce fameux machin qu'une méthode non synchronisée pouvait foutre le bordel sur un objet qui execute une méthode synchronisée. Mais j'ai pas vraiment capté ce principe donc si tu as des infos
Marsh Posté le 08-08-2002 à 14:41:51
DarkLord a écrit a écrit : ceci dit benou, HashSet ne sert vraiment à rien parce que là seule méthode qui le remplit prend comme argument un XXXEventListener |
ben c'est pas ca le problème, c'est juste que c'est lpus logique de mettre un Set qu'une Collection puisque tu veux qu'il n'y ait pas 2 fois le même event qui soit enregistré : t'auras pas besoin de faire le test pour savior si il est déjà dedans ...
Citation : |
ben si c'est obligé : c'est la méthode qui est synchronized.
La règle avec les synchronized c'est que tu ne pourra pas avoir 2 méthodes synchronized appelée en même temps sur la même instance => tu peux très bien appeler le addListener pendant l'executino du fireEvent ce qui va altérer ta ArrayList => l'Iterator sera dans un état instable => tu vas te manger une Error à des moments assez aléatoire ...
la solution c'est soit de mettre la méthode addListener en synchronized soit de vérouiller la liste pendant qu'on s'en sert, ce qui est d'ailleur plus propre :
Code :
|
Marsh Posté le 08-08-2002 à 14:46:42
DarkLord a écrit a écrit : . A moins qu'il y ait ce fameux machin qu'une méthode non synchronisée pouvait foutre le bordel sur un objet qui execute une méthode synchronisée. |
là ce dont tu parles c'est les problèmes d'interblocage (je crois que c'est comme ca que ca s'apelle). C'est quand tu apelles une méthode blocante (vérrouillée) alors que tu es toi même à l'intérieur d'un autre verrou sur autre instance d'objet : ca fait que les 2 s'attende mutuellement => blocage
fait une recherche sur google sur le problème des philosophes ou des producteurs-consomateurs en programation parallèle si ca t'intéresses.
(ca va rapeller des trucs à chapi si il traine dans le coin)
Marsh Posté le 08-08-2002 à 14:47:04
Marsh Posté le 08-08-2002 à 16:06:35
non ... ca me rappelle rien du tout
En anglais, ca s'appelle le DeadLock ! mais ca ne correspond pas vraiment a la problematique du prod-conso !
Le prod conso c'est exactement le meme probleme qu'avec les listener : avec un consommateur (le déclencheur d'événements) et le producteur (l'événements et son ajout dans la liste des évenements a traiter)!
Tiens, pour la peine, je me refile un
Marsh Posté le 08-08-2002 à 16:29:03
chapi456 a écrit a écrit : non ... ca me rappelle rien du tout En anglais, ca s'appelle le DeadLock ! mais ca ne correspond pas vraiment a la problematique du prod-conso ! Le prod conso c'est exactement le meme probleme qu'avec les listener : avec un consommateur (le déclencheur d'événements) et le producteur (l'événements et son ajout dans la liste des évenements a traiter)! Tiens, pour la peine, je me refile un |
multinick de qui?
Marsh Posté le 08-08-2002 à 17:04:42
veryfree a écrit a écrit : multinick de qui? |
bha de personne ... c'est chapi quoi ...
Marsh Posté le 08-08-2002 à 17:21:39
Et, si je décide de me passer de XXXMyServer, et d'inclure ses méthodes dans l'unique objet qui pourra lancer les evenements XXX (comme ça a l'air d'avoir été fait pour les Button Awt par exemple).
c "deprecated" cette façon de faire ?
Marsh Posté le 08-08-2002 à 17:34:30
bin c'est le cas dans mon exemple. Si tu veux une analogie, le XXXServer c'est un JComponent par exemple et le MyXXXServer c'est un JButton
Y a aucune différence
Et puis tout dépend de ce que tu veux générer comme évenement. Si la source n'a pas d'importance bin tu change ton XXXEvent pour qu'il te file d'autre info (comme un objet quelconque, une String ou d'autre truc). Tout dépend l'évenement que tu veux transmettre ...
Marsh Posté le 08-08-2002 à 17:38:47
DarkLord a écrit a écrit : bin c'est le cas dans mon exemple. Si tu veux une analogie, le XXXServer c'est un JComponent par exemple et le MyXXXServer c'est un JButton Y a aucune différence Et puis tout dépend de ce que tu veux générer comme évenement. Si la source n'a pas d'importance bin tu change ton XXXEvent pour qu'il te file d'autre info (comme un objet quelconque, une String ou d'autre truc). Tout dépend l'évenement que tu veux transmettre ... |
Ha, ok.
Vu vu le nom que t'avais donné à MyXXXServer, j'croyais que t'avais imaginé un truc du style des PropertyChangeSupport. Tu vois ce que j'veux dire ?
Marsh Posté le 08-08-2002 à 17:47:01
oulalal comme tu y vas toi
Non je pensais pas si loin. D'ailleurs c'est histoire de XXXServer et MyXXXServer qui compliquait inutilement le problème ...
Marsh Posté le 08-08-2002 à 17:51:39
DarkLord a écrit a écrit : oulalal comme tu y vas toi Non je pensais pas si loin. D'ailleurs c'est histoire de XXXServer et MyXXXServer qui compliquait inutilement le problème ... |
Mais g pas été attentif, j'aurais pu voir que dans ta méthode fireXXXEventPerformed, quand tu crés l'évènement, t'y attaches "this".
Pour un truc style PropertyChangeSupport, j'imagine que l'évènement prend pas this dans son constructeur. ça aurait pas trop de sens.
EDIT : G bon, g vérifié !
Marsh Posté le 08-08-2002 à 17:53:14
Merci en tout cas. C'était interressant en plus d'être utile.
(la partie des "synchronized", c pas vraiment compris, ms c pas grave, ça viendra + tard. ¨Pour ça, j'vais recopier bêtement
Marsh Posté le 08-08-2002 à 17:56:29
synchronized te permet de mettre un lock sur un objet. L'idée dans ce cas ci c'est que personne ne peut ajouter un listener pendant que tu parcours la liste pour envoyer les évenement aux clients.
donc en faisant
Code :
|
Ne pas utiliser ca a tout bout de champ parce que ca détruit les perfs ... C'est la raison principale qui fait que Vector est un Container très lent
Marsh Posté le 08-08-2002 à 18:58:29
juste une précision :
synchronized(listeners) { |
ce que j'ai mit en gras c'est pas tout à fait vrai : tu pourras encore manipuler l'objet synchronisé même si le bloc n'est pas terminé. Par contre, tu ne pourra pas entrer à nouveau dans un bloc synchronisé sur le même objet.
Je suis clair là ?
edit : pkoi ca vaut pas se mettre en gras ???
Marsh Posté le 09-08-2002 à 09:05:50
benou a écrit a écrit : juste une précision :
|
Ouais, c clair.
Mais alors dans notre cas, il faudra aussi synchroniser listeners dans la méthode d'ajout !
Un synchronize qui n'apparait qu'a un seul endroit dans un objet n'aurait pas de sens (enfin, si l'attribut synchronisé ne peut pas être accèdé par l'extérieur de l'objet).
Marsh Posté le 09-08-2002 à 09:08:12
El_Gringo a écrit a écrit : Ouais, c clair. Mais alors dans notre cas, il faudra aussi synchroniser listeners dans la méthode d'ajout ! Un synchronize qui n'apparait qu'a un seul endroit dans un objet n'aurait pas de sens (enfin, si l'attribut synchronisé ne peut pas être accèdé par l'extérieur de l'objet). |
ouais c'est ca ! et c'est ce que j'ai fait : regarde le code que j'avais donné.
et si ca a un sens : ca fait que 2 thread ne peuvent pas executer en même temps la méthode synchronisée
Marsh Posté le 09-08-2002 à 09:12:29
benou a écrit a écrit : ouais c'est ca ! et c'est ce que j'ai fait : regarde le code que j'avais donné. et si ca a un sens : ca fait que 2 thread ne peuvent pas executer en même temps la méthode synchronisée |
Ha ouais, j'avais pas vu.
Tient, j'avais pas pensé pour les threads. Mais de toute façon, synchroniser des attrubuts (ou des méthodes), ça n'a de sens que dans un cadre multi thread, non !?
Parce qu'en mono thread, le code n'est exécuté ne se passe qu'a un endroit à la fois (enfin, vous m'comprenez quoi !).
A moins que... certaines classes du JDK ou d'autres lib utilisent parfois plusieurs threads ?
Marsh Posté le 09-08-2002 à 09:18:15
y'a aussi dans le cas ou tu fais un serveur avec plusieurs clients (sans vraiment mettre en place de multi thread)
La tu pourrais avoir pas mal de probleme (surtout que comme par hazard, c'est toujours au MEME moment que 2 bozots vont faire la meme manip !
donc synchronized :
P.S. : Benou : on prend le grand lit chez loic ? (ou comment casser une reputation ....)
Marsh Posté le 09-08-2002 à 09:37:42
El_Gringo a écrit a écrit : Mais de toute façon, synchroniser des attrubuts (ou des méthodes), ça n'a de sens que dans un cadre multi thread, non !? |
ben oui mais par exemple, dès que tu fais des interfaces graphiques c'est multi-threadé !
Marsh Posté le 09-08-2002 à 09:39:01
chapi456 a écrit a écrit : P.S. : Benou : on prend le grand lit chez loic ? (ou comment casser une reputation ....) |
heu .... je plus très sur de vouloir aller aider loic, là d'un coup ...
Marsh Posté le 09-08-2002 à 10:59:00
benou a écrit a écrit : ben oui mais par exemple, dès que tu fais des interfaces graphiques c'est multi-threadé ! |
Ouais, donc du coup 'faut tjs penser multi thread. Surout que là je suis ds l'cadre d'une servlet.
J'ai compris comment ça marche synchronized (fini les mutex si g bien compris ! Y vont pas me manquer ceux là ).
Mais par contre, je vois pas à quel moment en mettre, et ou !
Parce que j'aurais envie d'en mettre partout finalement...
Marsh Posté le 09-08-2002 à 11:06:34
ben uniquement sur les objets qui sont partagés ...
dans le cadre des servlets faut faire attention parce que si t'en mets partout tu vas avior des temps de réopnses désastreux dès que tu auras plusieurs accès simultanés ...
pour les servlets, tu sera par exemple obligé d'en mettre si tu as un attribut de ta servlet qui est une arrayList par exemple et qu'elle est amenée à changer pendant que d'autres la lisent ...
Mais ce genre de trucs peut être réglé en fesant une copie de la ArrayList : si à un moment tu dois ajouter un élément, plutot que de faire un add(), tu fais une copie de la arraylist, tu fais un add sur la copie et tu remplace l'original par la copie. Comme la copie de référence est une opération atomoique, le problème ne se pose pas :
version de base :
Code :
|
version sans synchronized :
Code :
|
Marsh Posté le 09-08-2002 à 11:13:05
Mais, par exemlpe dans ma servlet, c quoi un objet partagé !?
une opération atomique c quoi ? c synchronisé automatiquement ?
Marsh Posté le 09-08-2002 à 11:22:58
ben ca tu devrais le savoir
ta servlet n'est instancié qu'une seule fois par le moteur de servlet : pour chaque requête vers la servlet, c'est toujours le même objet qui est appelé.
Donc, si plusieurs client appellent la même page en même temps, la servlet executera en parallèle (dans différents threads) plusieurs fois la méthode doGet ou doPost. Il n'y a pas de problème pour tous ls objets que tu vas déclarer à l'intérieur de ces méthodes car ils seront "isolés" (les autres thread ne les connaîtront pas), par contre, les attributs de ton objet servlet, eux ils sont accessible par ta méthode doGet ou doPost, donc ils sont accessible en même temps par plusieurs thread. Ils sont donc "partagés" avec les problèmes que ca pose ...
une opération atomique, c'est juste une instruction qui sera forcément fait "en un coup" par la machine. Dans ces cas là, tu es sur que tu n'auras pas de problème d'execution parallèles
Dans le cas de copie de référence, c'est atomique puisque ca correspond à une copie d'adresse mémoire.
quelques exemples :
Code :
|
Marsh Posté le 09-08-2002 à 11:40:44
benou a écrit a écrit : ben ca tu devrais le savoir ta servlet n'est instancié qu'une seule fois par le moteur de servlet : pour chaque requête vers la servlet, c'est toujours le même objet qui est appelé. Donc, si plusieurs client appellent la même page en même temps, la servlet executera en parallèle (dans différents threads) plusieurs fois la méthode doGet ou doPost. Il n'y a pas de problème pour tous ls objets que tu vas déclarer à l'intérieur de ces méthodes car ils seront "isolés" (les autres thread ne les connaîtront pas), par contre, les attributs de ton objet servlet, eux ils sont accessible par ta méthode doGet ou doPost, donc ils sont accessible en même temps par plusieurs thread. Ils sont donc "partagés" avec les problèmes que ca pose ... une opération atomique, c'est juste une instruction qui sera forcément fait "en un coup" par la machine. Dans ces cas là, tu es sur que tu n'auras pas de problème d'execution parallèles Dans le cas de copie de référence, c'est atomique puisque ca correspond à une copie d'adresse mémoire. quelques exemples :
|
Super bien expliqué, merci Benou !
Pour les objets partagés, en fait je le savais. Ms j'y ai pas pensé sur le coup. Et j'avais pas imaginé les conséquences que ça pouvait avoir. J'vais ajouter qqs synchronized ds mon code.
Et donc, dans une servlet qui est pas explicitement multi thread, les seuls objets "partagés" sont les attributs de ma classe servlet, c ça ?
opération atomique, ouais, j'aurais pu m'en douter !
Ms on devrait appaler ça des opération quarkiques, l'image serait plus juste !
Marsh Posté le 09-08-2002 à 11:44:14
El_Gringo a écrit a écrit : Super bien expliqué, merci Benou ! |
Citation : Et donc, dans une servlet qui est pas explicitement multi thread, les seuls objets "partagés" sont les attributs de ma classe servlet, c ça ? |
une servlet est TOUJOURS multithreadée !
et non, y a pas forcément que les attributs ... y a aussi tous les objets communs à ton application (dans le ServletContext) ou tes les objets statiques, etc ...
et évite de foutre des synchronized partout. Imagine un peu les conséquences !
Marsh Posté le 09-08-2002 à 11:49:27
benou a écrit a écrit : une servlet est TOUJOURS multithreadée ! |
"implements SingleThreadModel"
ou qqchose comme ça
Marsh Posté le 09-08-2002 à 11:55:22
benou a écrit a écrit :
|
Je voulais dire, si on cré pas des thread autres que ceux gérés par le moteur de servlet.
J'imagine les conséquences. J'imagine. J'ai déja été confronté à ça. g vu tourner une appli ou tous les accès BD étaient synchronizés (c pas moi qui l'ai faite !). c'était terrible !
Marsh Posté le 09-08-2002 à 11:58:23
--greg-- a écrit a écrit : "implements SingleThreadModel" ou qqchose comme ça |
je connais pas ca ... t'es sur de ton coup là ?
et puis bon, tu peux facilement monothreader ta servlet en synchronisant la méthode service mais c'est vraiment imonde !
Marsh Posté le 09-08-2002 à 11:59:05
vi vi si tu implémentes SingleThreadModel c'est une seule instance et un seul appel à la fois
Marsh Posté le 08-08-2002 à 10:56:28
Je connais pour ainsi dire, rien du tout, à la gestion des evênements en Java.
Là, je suis en train d'écrire une classe. Je voudrais que, quand on change certains trucs, un listener de ma création puisse capter des messages.
L'élément qu'y me manque, c'est : comment lancer un évènement ?