besoin d'un expert en Thread !!! [JAVA] - Programmation
Marsh Posté le 15-05-2001 à 17:30:39
sans bcp de conviction essaye de faire un System.gc() juste apres avoir fait th=null pour forcer le garbage collector a vraiement detruire le 1er thread.
Sinon, le thread qui a ete cree sur le premier clic est toujours en vie qd tu clique la 2eme fois?
Et le th, c'est defini ou?
Et si tu veux en finir avec un thread, la methode propre c'est de sortir de sa boucle run.
[edit]--Message édité par wpk--[/edit]
Marsh Posté le 15-05-2001 à 17:34:36
Ben le problème est que la méthode run se finit bien !
c'est réellement incompréhensible...
th c défini comme attribut de classe :
c un Thread lancé a partir d'une classe Runnable que j'ai créée.
le runnable est initialisé dans init()
th est initialisé au clic de souris donc dans la méthode correspondante...
Marsh Posté le 15-05-2001 à 17:40:39
et ta servlette, elle ne garde pas une reference sur ton premier thread?
Marsh Posté le 15-05-2001 à 17:44:30
Non aucun rapport car avant d'utiliser une servlette j'utilisais un script CGi lourd c'est pour ca que je suis passé aux servlets
Marsh Posté le 15-05-2001 à 20:47:00
Surotut ne pas utiliser les methodes destroy() ou stop() pour les threads , ca fout la merde pas possible et c est deconseillé par SUn
Marsh Posté le 15-05-2001 à 22:26:59
Tu utilises quoi comme Listener pour tes boutons ???
Si c MouseListener essaye plutôt ActionListener et implémente la méthode actionPerformed.
Sinon pour stopper ton thread, avec stop() on maitrise pas trop ce qui se passe et destroy() n'est pas implémentée enfin si tu as juste throw new NoSuchMethodError(); donc comme dit ragefan laisse tomber ces méthodes.
Essaye plutôt ca :
class AirbgThread extends Thread
{
private volatile boolean stop;
public void stopper()
{
stop = true;
}
public void run()
{
while(!stop)
{
// tes traitements
}
}
}
Dès que tu invoques stopper() la méthode run() se termine proprement et ton thread sera supprimé.
Marsh Posté le 15-05-2001 à 22:58:57
Non en fait, les threads se terminent tout seuls (fin normale du run) mais je les relances en refaisant monthread = new Thread(...)
monthread.run(); Et c'est la sans dout e que ca merde...
Marsh Posté le 15-05-2001 à 23:44:02
Si ca marche tjs pas donne ton code, c peut-être un pb qui vient d'ailleurs
Marsh Posté le 15-05-2001 à 23:52:51
ca m'etonnerait bcp que tu appelle le run. En appelant le run, y'a plus de multithreading !
[edit]--Message édité par wpk--[/edit]
Marsh Posté le 16-05-2001 à 09:53:53
faute de frappe j'utilise monthread.start();
voici un bout de code :
classe CGI (implements runnable)
----------
public void run()
{
if (_nbth == 0 | _nbth == 1)
{
synchronized(_conf)
{
_conf.disablee(); // disable les boutons
}
}
executeCGI(_url_cgi);
try
{
Thread.sleep(500);
}
catch (InterruptedException ie) {}
synchronized(_conf)
{
if (_pgbar) _conf.advanceBar();
if (_nbth == 0 | _nbth == 8 | _nbth == 9)
_conf.enablee(); // enable bouton
}
}
Applet :
--------
private Thread _th1; // Thread correspondant au premier bouton
private Thread _th2; // 2e
private Thread[] _groupTh; // 3e
private CGIs[] _cgis; // classe du dessus (Runnable)
private CGIs _cgi1;
private CGIs _cgi2;
dans init()
...
_cgi1 = new CGIs("http://15.129.22.198:8080/servlet/ConsoleRouterServlet", ta, this, false, 0);
_cgi2 = new CGIs("http://15.129.22.198:8080/servlet/PingTFTPServlet", ta, this, false, 0);
_cgis[0] = new CGIs("http://15.129.22.198:8080/servlet/ConfServlet?ip=15.129.22.201&file=template-r1-confg&router=R1", ta, this, true, 1);
_cgis[1] = new CGIs("http://15.129.22.198:8080/servlet/ConfServlet?ip=15.129.22.202&file=template-r2-confg&router=R2", ta, this, true, 2);
_cgis[2] = new CGIs("http://15.129.22.198:8080/servlet/ConfServlet?ip=15.129.22.203&file=template-r3-confg&router=R3", ta, this, true, 3);
_cgis[3] = new CGIs("http://15.129.22.198:8080/servlet/ConfServlet?ip=15.129.22.204&file=template-r4-confg&router=R4", ta, this, true, 4);
_cgis[4] = new CGIs("http://15.129.22.198:8080/servlet/ConfServlet?ip=15.129.22.205&file=template-r5-confg&router=R5", ta, this, true, 5);
_cgis[5] = new CGIs("http://15.129.22.198:8080/servlet/ConfServlet?ip=15.129.22.206&file=template-r6-confg&router=R6", ta, this, true, 6);
_cgis[6] = new CGIs("http://15.129.22.198:8080/servlet/ConfServlet?ip=15.129.22.207&file=template-r7-confg&router=R7", ta, this, true, 7);
_cgis[7] = new CGIs("http://15.129.22.198:8080/servlet/ConfServlet?ip=15.129.22.208&file=template-r8-confg&router=R8", ta, this, true, 8);
_cgis[8] = new CGIs("http://15.129.22.198:8080/servlet/ConfServlet?ip=15.129.22.209&file=template-r9-confg&router=R9", ta, this, true, 9);
}
...
enfin sur un ActionListener :
-----------------------------
premier bouton
_th1 = new Thread(_cgi1);
_th1.start(); --> a chaque clic c ca qu'il se passe.
J'espere ne pas etre trop confus.
Marsh Posté le 16-05-2001 à 10:16:36
Stop Thread
jvmdiError
StopThread(jthread thread, jobject exception)
Send the specified asynchronous exception to the specified thread (similar to java.lang.Thread.stop). Normally, this function is used to kill the specified thread with an instance of the exception ThreadDeath.
>ragefan ?
? pourquoi ça fout la merde les stop thread ?
Marsh Posté le 16-05-2001 à 10:23:25
[FDS] a écrit a écrit : Tu utilises quoi comme Listener pour tes boutons ??? Si c MouseListener essaye plutôt ActionListener et implémente la méthode actionPerformed. Sinon pour stopper ton thread, avec stop() on maitrise pas trop ce qui se passe et destroy() n'est pas implémentée enfin si tu as juste throw new NoSuchMethodError(); donc comme dit ragefan laisse tomber ces méthodes. Essaye plutôt ca : class AirbgThread extends Thread { private volatile boolean stop; public void stopper() { stop = true; } public void run() { while(!stop) { // tes traitements } } } Dès que tu invoques stopper() la méthode run() se termine proprement et ton thread sera supprimé. |
Aie....
Il manque des Mutex pour proteger ta variable stop !
Marsh Posté le 16-05-2001 à 10:45:47
Marsh Posté le 16-05-2001 à 10:58:30
Pas besoin stop est volatile
La mémoire de travail des threads est mise en phase avec la mémoire principale à chaque accès à stop.
Marsh Posté le 16-05-2001 à 11:02:19
merci mais ca résoud pas mon probleme ca.
les a la fin du run , les boutons sont remis enable et je peux a nouveau cliquer dessus. DOnc en théorie tous les threads sont morts mais en pratique (ce n'est pas systématique pourtant) quand je reclique sur le Premier bouton g un double affichage, autrement 2 threads qui se lancent au lieu d'un !
Marsh Posté le 16-05-2001 à 13:03:49
je sais pas si ca va resoudre to prob mais en sorte qu'il n'y ai une seule classe qui lance les thread parceque ca evite des problemes comme la liberation de la memoire ... peut etre que ca va resoudre le tient
bonne chance !
Marsh Posté le 16-05-2001 à 13:29:01
ben c'est ce que je fais...
Marsh Posté le 16-05-2001 à 14:19:54
[FDS] a écrit a écrit : Pas besoin stop est volatile La mémoire de travail des threads est mise en phase avec la mémoire principale à chaque accès à stop. |
certainement pas !
le volatile t'assure que ton while(!stop) ne sera pas optimise en while(true) un point c'est tout.
par contre ton stop est un bool ce qui pourrait te faire dire que l'acces a stop est atomique...
Sur une machine a plusieurs proc, on ne joue pas avec des supositions comme ca... Mieux vaut mettre un Mutex.
Marsh Posté le 16-05-2001 à 14:27:49
vous disputez pas
tout ce qque vous dites ne résoud pas mon problème malheureusement...
Marsh Posté le 16-05-2001 à 15:24:29
airbg a écrit a écrit : vous disputez pas tout ce qque vous dites ne résoud pas mon problème malheureusement... |
Si utilise le stop comme le defini FDS et teste le regulierement dans la Thread pour la terminer, c'est la methode la plus propre.
Verifie que ton Listener n'est pas appele plusieurs fois pour un clic...
Sinon utilise un Thread Pool, c'est ce qui est le plus performant en multithreading...
Marsh Posté le 16-05-2001 à 21:44:03
BENB a écrit a écrit : certainement pas ! le volatile t'assure que ton while(!stop) ne sera pas optimise en while(true) un point c'est tout. par contre ton stop est un bool ce qui pourrait te faire dire que l'acces a stop est atomique... Sur une machine a plusieurs proc, on ne joue pas avec des supositions comme ca... Mieux vaut mettre un Mutex. |
N'importe quoi
Je n'ai jamais dit qu'étant donné que stop est un booléen l'acces est atomique, c'est volatile qui fait que la variable est atomique.
Tu as 2 méthodes soit tu mets ta variable volatile ou tu utilises synchronized.
volatile autorise la concurrence d'accès et la mémoire de travail de tes threads est en phase evec la mémoire principale à chaque accès à stop (rien à voir avec l'optimisation ???). Avec synchronized (mutex) la mise en phase se fait à chaque libération du verrou donc pas de concurrence. Mais l'accès à ta variable sera atomique dans les 2 cas.
Marsh Posté le 16-05-2001 à 21:55:02
lamatrice :
Oui va voir dans l'aide du jdk 1.3 de Sun dans la classe Thread , tu verras
Marsh Posté le 16-05-2001 à 23:40:14
BENB > qu'appelles-tu un thread pool ?
Marsh Posté le 17-05-2001 à 00:07:49
BENB> [FDS] a raison, volatile est indiqué dans ce cas. En plus la variable n'est pas partagée par d'autres threads, pas besoin de lock.
[edit]--Message édité par Verdoux--[/edit]
Marsh Posté le 17-05-2001 à 09:52:38
airbg a écrit a écrit : BENB > qu'appelles-tu un thread pool ? |
Il y a plusieurs algos. Le principe est de creer plusieurs threads et de ne pas les detruire, mais plutot de les reutiliser.
Generalement il y a une queue de tache a accomplir et chaque Thread du pool prend une tache dans la queue, et l'accompli. lorsqu'il n'y a plus de taches dans la queue, la thread qui n'a plus rien a faire s'endors, ou eventullemeent meurs sil il y a beaucoups de threads, et quand tu ajoutes une tache dans la queue tu reveille une thread s'il y en a une endormie. Si aucune n'est disponible tu peut eventuellement en creer une nouvelle.
Le principe est de minimiser les creations destructions de threads, et de travailler en patron/employe, la thread principale est le patron et celles du pool les employes, le role de la thread principal etant de charger le pool.
C'est ce que j'utilise (en C++) en evitant de changer le nombre de threads du pool.
En plus tu peut mettre une option pour travailler en monothread dans la fonction qui charge le pool. Comme ca c'est plus facile pour debugger !
Marsh Posté le 17-05-2001 à 10:10:38
[FDS] a écrit a écrit : N'importe quoi Je n'ai jamais dit qu'étant donné que stop est un booléen l'acces est atomique, c'est volatile qui fait que la variable est atomique. Tu as 2 méthodes soit tu mets ta variable volatile ou tu utilises synchronized. volatile autorise la concurrence d'accès et la mémoire de travail de tes threads est en phase evec la mémoire principale à chaque accès à stop (rien à voir avec l'optimisation ???). Avec synchronized (mutex) la mise en phase se fait à chaque libération du verrou donc pas de concurrence. Mais l'accès à ta variable sera atomique dans les 2 cas. |
Pardon j'ai confondu avec le C++, honte a moi...
Apparement les acces sur les booleens sont de toute facon atomiques en Java
Citation : If a double or long variable is not declared volatile, then for the purposes of load, store, read, and write actions they are treated as if they were two variables of 32 bits each: wherever the rules require one of these actions, two such actions are performed, one for each 32-bit half. The manner in which the 64 bits of a double or long variable are encoded into two 32-bit quantities is implementation-dependent. The load, store, read, and write actions on volatile variables are atomic, even if the type of the variable is double or long. |
Marsh Posté le 17-05-2001 à 10:45:09
BOn merci à tous. La solution du thread pool de benb me parait bonne mais je n'ai malheureusement pas le temps de l'implanter
Par ailleurs d'autres bugs se sont manifestés et il me reste 1 semaine avant déploiement du projet... (je dois faire la doc, la demo ...argggg chuis foutu).
Encore merci je m'endormirai moins con ce soir
Marsh Posté le 15-05-2001 à 17:07:19
Bon voila mon ENORME problème que ca fait 107 ans que je suis dessus :
- J'ai réalisé une applet multithreadée
- Cette applet dispose de trois boutons:
- le premier pour créer un thread qui appelle une servlet (résultat affiché dans un TextArea)
- le deuxieme comme le premier.
- le dernier lorsque l'on clique dessus crée 9 threads en parallèles qui appelle une servlet (chargement de config dans des routeurs c'est un peu lourd mais ca marche).
Voila le probleme :
- Lorsque je clique sur le 1er : OK
- Lorsque je clique sur le 2e : OK
- 3e : OK
- reclic sur le premier : 2 threads se lancent
C'est comme si je cliquais 2 fois très vite !
Pourtant a chaque clic je vérifie si les threads existent encore
(if (th != null) th = null, quand je veux faire un destroy j'au un NoSuchMethodError)....
Quelqu'un peut m'aider svp ? c'est trop urgent !!! Merci
---------------
"There's not such a thing as a stupid question, only stupid people..."