Bonjour à tous,

J'ai un problème qui dépend visiblement de l'environnement d'exécution.

Dans l'idée, mon programme est le suivant :
1. je crée une JApplet, qui lance un Thread,
2. lorsque je ferme I.E., la méthode stop() puis destroy() de l'applet est appelée,
3. j'ai demandé à la méthode destroy() de demander au thread de s'arrêter proprement. Je fais cela en positionnant à true un boolean dans le tread qui lui indique de s'arrêter,
4. la méthode destroy() est censée attendre avant de se terminer que le thread se soit réellement arrêté (test de thread.isAlive()).

Mon problème est le suivant :
1. cela marche parfaitement si je fais un clique-droit > Run File dans Netbeans sur la classe de l'applet JApplet_Main
2. en revanche, si j'exécute directement le fichier HTML qui intègre l'applet, la méthode stop() s'arrête au bout de quelques millisec (genre kill -9), et ne laisse pas le temps au thread de s'arrêter.

J'ai fait un code simplifié qui permet d'illustrer ce que je veux dire :

Code de l'applet :
Code : Sélectionner tout - Visualiser dans une fenêtre à part
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
 
import javax.swing.JApplet;
 
import org.apache.log4j.*;
 
public class JApplet_Main extends JApplet {
 
    private final Logger _logger = Logger.getLogger(JApplet_Main.class);
 
    RunningThread _thread;
 
    public void start() {
        _thread = new RunningThread("UN");
        _thread.start();
    }
 
    public void stop() {
        _logger.debug("stop()");
    }
 
    public void destroy() {
        _logger.debug("destroy()");
 
        _thread.requestToStop();
 
        _logger.debug("Delaying the end of the stop() method");
        while(_thread.isAlive()) {
            try {
                _logger.debug("The thread is still alive");
                Thread.sleep(100);
            }
            catch (InterruptedException exception) {
                _logger.error("InterruptedException caught while waiting : " + exception);
            }  
        }
        _logger.debug("The thread died by itself");
    }
}
Code du Thread :
Code : Sélectionner tout - Visualiser dans une fenêtre à part
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
 
import org.apache.log4j.*;
 
public class RunningThread extends Thread {
 
    private Logger _logger = Logger.getLogger(RunningThread.class);
    String _label;
    boolean _mustStop;
 
    RunningThread(String myLabel) {
        _label = myLabel;
        _mustStop = false;
    }
 
    public void requestToStop() {
        _logger.debug("Thread " + _label + " has been requested to stop");
        _mustStop = true;
    }
 
    public void run() {
        while (! _mustStop) {
            _logger.info("Thread " + _label + " is alive");
 
            for (long i=0; i<1000000000;i++)
            {
                // it is useless to use Thread.sleep() as it is interrupted 
                // while stopping the applet
                // better do nothing, but a huge number of times
            } // for
        } // while
        _logger.debug("The loop of thread " + _label + " has been stopped");
    }
}
Code du fichier HTML (au besoin) :
Code : Sélectionner tout - Visualiser dans une fenêtre à part
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
 
<HTML>
<HEAD>
   <TITLE>Applet HTML Page</TITLE>
</HEAD>
<BODY>
 
<H3><HR WIDTH="100%">Applet HTML Page<HR WIDTH="100%"></H3>
 
<P>
<APPLET codebase="..\dist" archive="TestThreadApplet.jar,log4j-1.2.15.jar" code="JApplet_Main.class" width=350 height=200></APPLET>
</P>
 
<HR WIDTH="100%"><FONT SIZE=-1><I>Generated by NetBeans IDE</I></FONT>
</BODY>
</HTML>
Si j'exécute ce code sous Netbeans (clique droit > Run File sur la classe JApplet_Main), j'obtiens :
09-04-27 19:27:06 (RunningThread,run) INFO : Thread UN is alive
09-04-27 19:27:07 (RunningThread,run) INFO : Thread UN is alive
09-04-27 19:27:09 (RunningThread,run) INFO : Thread UN is alive
--> C'est à ce moment que je ferme la fenêtre qui est apparue quand j'ai exécuté la classe Main_Applet sous Netbeans (clique-droit > Run File) <--
09-04-27 19:27:10 (JApplet_Main,stop) DEBUG : stop()
09-04-27 19:27:10 (JApplet_Main,destroy) DEBUG : destroy()
09-04-27 19:27:10 (RunningThread,requestToStop) DEBUG : Thread UN has been requested to stop
09-04-27 19:27:10 (JApplet_Main,destroy) DEBUG : Delaying the end of the stop() method
09-04-27 19:27:10 (JApplet_Main,destroy) DEBUG : The thread is still alive
09-04-27 19:27:10 (JApplet_Main,destroy) DEBUG : The thread is still alive
09-04-27 19:27:10 (JApplet_Main,destroy) DEBUG : The thread is still alive
09-04-27 19:27:10 (JApplet_Main,destroy) DEBUG : The thread is still alive
09-04-27 19:27:10 (JApplet_Main,destroy) DEBUG : The thread is still alive
09-04-27 19:27:10 (JApplet_Main,destroy) DEBUG : The thread is still alive
09-04-27 19:27:10 (JApplet_Main,destroy) DEBUG : The thread is still alive
09-04-27 19:27:10 (JApplet_Main,destroy) DEBUG : The thread is still alive
09-04-27 19:27:10 (JApplet_Main,destroy) DEBUG : The thread is still alive
09-04-27 19:27:10 (RunningThread,run) DEBUG : The loop of thread UN has been stopped
09-04-27 19:27:11 (JApplet_Main,destroy) DEBUG : The thread died by itself
<-- le thread s'est arrêté normalement, l'applet l'a vu, tout est donc normal -->
En revanche, si je lance directement le fichier HTML qui contient l'applet, j'ai les logs suivants :
09-04-27 19:33:01 (RunningThread,run) INFO : Thread UN is alive
09-04-27 19:33:03 (RunningThread,run) INFO : Thread UN is alive
09-04-27 19:33:04 (RunningThread,run) INFO : Thread UN is alive
--> C'est à ce moment que je ferme I.E. <--
09-04-27 19:33:05 (JApplet_Main,stop) DEBUG : stop()
09-04-27 19:33:05 (JApplet_Main,destroy) DEBUG : destroy()
09-04-27 19:33:05 (RunningThread,requestToStop) DEBUG : Thread UN has been requested to stop
09-04-27 19:33:05 (JApplet_Main,destroy) DEBUG : Delaying the end of the stop() method
09-04-27 19:33:05 (JApplet_Main,destroy) DEBUG : The thread is still alive
09-04-27 19:33:05 (JApplet_Main,destroy) DEBUG : The thread is still alive
09-04-27 19:33:05 (JApplet_Main,destroy) DEBUG : The thread is still alive
09-04-27 19:33:05 (JApplet_Main,destroy) ERROR : InterruptedException caught while waiting : java.lang.InterruptedException: sleep interrupted
09-04-27 19:33:05 (JApplet_Main,destroy) DEBUG : The thread is still alive
09-04-27 19:33:05 (JApplet_Main,destroy) DEBUG : The thread is still alive
09-04-27 19:33:05 (JApplet_Main,destroy) DEBUG : The thread is still alive
<-- fin du fichier, la JVM s'arrête et le thread n'a pas eu le temps de s'arrêter <--
Ma question est la suivante :
  • est-il possible de dire à la JVM de ne s'arrêter qu'à la fin des threads (c'est le comportement par défaut pour une Java Application, mais visiblement pas pour une applet)
  • est-il possible de désactiver ou de rallonger le timewatch (chien de garde en français, je crois) qui fait que les traitements dans la méthode destroy() de l'applet ne doivent pas durer plus de nnn millisecondes ?