IdentifiantMot de passe
Loading...
Mot de passe oublié ?Je m'inscris ! (gratuit)
Navigation

Inscrivez-vous gratuitement
pour pouvoir participer, suivre les réponses en temps réel, voter pour les messages, poser vos propres questions et recevoir la newsletter

Concurrence et multi-thread Java Discussion :

Thread - Sortir de la boucle while


Sujet :

Concurrence et multi-thread Java

  1. #1
    Candidat au Club
    Homme Profil pro
    Administrateur systèmes et réseaux
    Inscrit en
    Août 2014
    Messages
    2
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 39
    Localisation : France, Yvelines (Île de France)

    Informations professionnelles :
    Activité : Administrateur systèmes et réseaux
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Août 2014
    Messages : 2
    Points : 3
    Points
    3
    Par défaut Thread - Sortir de la boucle while
    Bonjour à tous,

    Tout d'abord je tiens à remercier toute la communauté pour son implication, vous n'avez pas idée comment vos remarques sont pertinentes pour des débutants.

    C'est la première fois que je poste sur un forum, je pense vraiment avoir fait le tour des ressources (peut-être je me trompe, mais après 6 jours de recherche...).
    Bref, voici mon "problème".


    A l'aide d'un bouton je lance un thread qui affiche un texte toutes les secondes.
    Quand je lance un autre bouton, le booléen passe à "false" et je devrais sortir de la boucle... Mais non...
    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
     
    private void printLog(final boolean runit) {
            Thread thread = new Thread(new Runnable() {
                @Override
                public void run() {
                	System.out.println("On RUN");
                	System.out.println("runit = " + runit);
                    while (runit) {
                        System.out.println("Time now is " + (new Date()));
                        try {
                            Thread.sleep(1000);
                        } catch (InterruptedException ex) {
                            ex.printStackTrace();
                        }
                    }
                }
            });
     
            if(runit){
    	        System.out.println("thread start");
    	        thread.start();
            }
            else{
     
            	System.out.println("thread interrupt");
                thread.interrupt();
            }
    }

    Merci par avance de vos contributions!

  2. #2
    Modérateur
    Avatar de joel.drigo
    Homme Profil pro
    Ingénieur R&D - Développeur Java
    Inscrit en
    Septembre 2009
    Messages
    12 430
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 54
    Localisation : France, Paris (Île de France)

    Informations professionnelles :
    Activité : Ingénieur R&D - Développeur Java
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Septembre 2009
    Messages : 12 430
    Points : 29 131
    Points
    29 131
    Billets dans le blog
    2
    Par défaut
    Salut,

    La boucle while s'effectue tant que runit est true, il est nécessaire qu'il passe à false à un moment donnée pour qu'on sorte de la boucle. Le fait qu'il soit final empêche absolument cette possibilité. La méthode interrupt() de Thread ne provoque qu'un changement d'état d'un flag, qui permet de forcer les actions "bloquantes" à s'interrompre, en utilisant une exception. L'appel à Thread.sleep() fait partie des actions bloquantes (Object.wait() en est une autre, par exemple).

    Il faut donc absolument passer runit à false pour arrêter le thread. L'appel à interrupt() fera que le thread n'attendra pas la fin de l'attente des une secondes pour continuer la boucle, donc tester l'état runit, donc s'arrêter. Il s'agit donc de permettre un arrêt immédiat ou pas.

    Exemple complet :

    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
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    49
    50
    51
    52
    53
    54
    55
    56
    57
    58
    59
    60
    61
    62
    63
    64
    65
    66
    67
    68
    69
    70
    71
    72
    73
    74
    75
    76
    77
    78
    79
    80
    81
    82
    83
    84
    85
    86
    87
    88
    89
    90
    91
    92
    93
    94
    95
    96
    97
    98
    99
    100
    101
    102
    103
    104
    105
    106
    107
    public class ThreadDemo {
     
    	private MyThread thread;  
     
        private static class MyThread extends Thread { 
     
        	private boolean runit;
     
        	@Override
            public void run() {
        		runit=true;
            	System.out.println("Thread is started");
                while (runit) {
                    System.out.println("Time now is " + (new Date()));
                    try {
                        Thread.sleep(1000);
                    } catch (InterruptedException ex) {
                        ex.printStackTrace();
                        // ici on pourrait mettre runit=false, si on veut arrêter le thread sur des interruptions envoyées par d'autres codes que le nôtre
                    }
                }
            	System.out.println("Thread is stopped");
            } 
     
            public void stopThread(boolean now) {
            	runit=false;
            	if ( now ) {
            		interrupt(); // force le thread à ne pas attendre la fin du sleep()
            	}
            }
     
        }
     
    	public static void main(String[] args) {
     
    		new ThreadDemo().run();
     
    	}
     
    	public void run() {
    		JFrame frame = new JFrame("Demo");
     
    		JButton buttonStart = new JButton("START");
    		buttonStart.setEnabled(true);
    		JButton buttonStop = new JButton("STOP");
    		buttonStop.setEnabled(false);
    		JButton buttonStopNow = new JButton("STOP NOW");
    		buttonStopNow.setEnabled(false);
    		buttonStart.addActionListener((event) -> {
    			startThread();
    			buttonStart.setEnabled(false);
    			buttonStop.setEnabled(true);
    			buttonStopNow.setEnabled(true);
    		});
    		buttonStop.addActionListener((event) -> {
    			stopThread(false);
    			buttonStop.setEnabled(false);
    			buttonStopNow.setEnabled(false);
    			buttonStart.setEnabled(true);
    		});
    		buttonStopNow.addActionListener((event) -> {
    			stopThread(true);
    			buttonStop.setEnabled(false);
    			buttonStopNow.setEnabled(false);
    			buttonStart.setEnabled(true);
    		});
    		frame.getContentPane().setLayout(new GridLayout(3, 0));
    		frame.getContentPane().add(buttonStart);
    		frame.getContentPane().add(buttonStop);
    		frame.getContentPane().add(buttonStopNow);
     
    		frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); // Pour la démo (le thread sera arrêté brutalement)
    		frame.pack();
    		frame.setLocationRelativeTo(null);
    		frame.setVisible(true);
     
    		/** Si la close operation n 'est pas EXIT-ON_CLOSE, le thread ne s'arrêtera pas, donc on utilisera un écouteur sur la fermeture de fenêtre tel que celui-ci
                    frame.addWindowListener(new WindowAdapter() {
                            @Override
                            public void windowClosed(WindowEvent e) {
                                    if ( thread!=null ) {
                                            thread.stopThread(now);
                                    }
                            }
                    });
                    */
     
    	}
     
        private void startThread() {
        	if ( thread==null ) {
        		thread = new MyThread();
        		thread.start();
        	}
        }
     
        /**
          * @now true = arrêt immédiat, false = arrêt au bout du temps d'attente
          */
        private void stopThread(boolean now) {
        	if ( thread!=null ) {
        		thread.stopThread(now);
        		thread=null;
        	}
        }
     
    }
    L'expression "ça marche pas" ne veut rien dire. Indiquez l'erreur, et/ou les comportements attendus et obtenus, et donnez un Exemple Complet Minimal qui permet de reproduire le problème.
    La plupart des réponses à vos questions sont déjà dans les FAQs ou les Tutoriels, ou peut-être dans une autre discussion : utilisez la recherche interne.
    Des questions sur Java : consultez le Forum Java. Des questions sur l'EDI Eclipse ou la plateforme Eclipse RCP : consultez le Forum Eclipse.
    Une question correctement posée et rédigée et vous aurez plus de chances de réponses adaptées et rapides.
    N'oubliez pas de mettre vos extraits de code entre balises CODE (Voir Mode d'emploi de l'éditeur de messages).
    Nouveau sur le forum ? Consultez Les Règles du Club.

  3. #3
    Candidat au Club
    Homme Profil pro
    Administrateur systèmes et réseaux
    Inscrit en
    Août 2014
    Messages
    2
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 39
    Localisation : France, Yvelines (Île de France)

    Informations professionnelles :
    Activité : Administrateur systèmes et réseaux
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Août 2014
    Messages : 2
    Points : 3
    Points
    3
    Par défaut
    Parfait MERCI beaucoup !!!!

  4. #4
    Expert éminent sénior
    Avatar de adiGuba
    Homme Profil pro
    Développeur Java/Web
    Inscrit en
    Avril 2002
    Messages
    13 938
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France

    Informations professionnelles :
    Activité : Développeur Java/Web
    Secteur : Transports

    Informations forums :
    Inscription : Avril 2002
    Messages : 13 938
    Points : 23 190
    Points
    23 190
    Billets dans le blog
    1
    Par défaut
    Salut,


    Citation Envoyé par joel.drigo Voir le message
    Exemple complet :
    J'aurais juste une toute petite correction à faire sur la déclaration de l'attribut booléen :
    Il faut le déclarer en volatile !
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
        	private volatile boolean runit;
    Pourquoi ?
    Parce que sur un vrai multi-CPU, il est possible que les threads tournent sur des CPU différents avec des zones mémoires différentes.
    La JVM pourrait très bien optimiser les accès à la variable (en recopiant la valeur de l'attribut "runit" dans le cache CPU), ce qui pourrait empêcher le thread de voir les modifications extérieure...

    Le problème n'est pas évident à démontrer, mais dès qu'on accède à une variable depuis différents threads il est impératif d'utiliser volatile (ou de mettre en place une synchronisation).


    a++

  5. #5
    Modérateur
    Avatar de joel.drigo
    Homme Profil pro
    Ingénieur R&D - Développeur Java
    Inscrit en
    Septembre 2009
    Messages
    12 430
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 54
    Localisation : France, Paris (Île de France)

    Informations professionnelles :
    Activité : Ingénieur R&D - Développeur Java
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Septembre 2009
    Messages : 12 430
    Points : 29 131
    Points
    29 131
    Billets dans le blog
    2
    Par défaut
    Citation Envoyé par adiGuba Voir le message
    J'aurais juste une toute petite correction à faire sur la déclaration de l'attribut booléen :
    Il faut le déclarer en volatile !
    En effet, un oubli de ma part, pour être effectivement complet.
    L'expression "ça marche pas" ne veut rien dire. Indiquez l'erreur, et/ou les comportements attendus et obtenus, et donnez un Exemple Complet Minimal qui permet de reproduire le problème.
    La plupart des réponses à vos questions sont déjà dans les FAQs ou les Tutoriels, ou peut-être dans une autre discussion : utilisez la recherche interne.
    Des questions sur Java : consultez le Forum Java. Des questions sur l'EDI Eclipse ou la plateforme Eclipse RCP : consultez le Forum Eclipse.
    Une question correctement posée et rédigée et vous aurez plus de chances de réponses adaptées et rapides.
    N'oubliez pas de mettre vos extraits de code entre balises CODE (Voir Mode d'emploi de l'éditeur de messages).
    Nouveau sur le forum ? Consultez Les Règles du Club.

+ Répondre à la discussion
Cette discussion est résolue.

Discussions similaires

  1. Réponses: 2
    Dernier message: 16/12/2012, 19h52
  2. Sortir d'une boucle while
    Par chris81 dans le forum Windows Forms
    Réponses: 7
    Dernier message: 21/01/2008, 11h50
  3. sortir de la boucle while
    Par bi_turbo dans le forum C++
    Réponses: 8
    Dernier message: 30/07/2007, 18h50
  4. Probleme pour sortir d'une boucle while
    Par aikinhdo dans le forum Langage
    Réponses: 0
    Dernier message: 27/07/2007, 15h01
  5. Sortir de la boucle while
    Par brindacier dans le forum MATLAB
    Réponses: 7
    Dernier message: 14/03/2007, 11h53

Partager

Partager
  • Envoyer la discussion sur Viadeo
  • Envoyer la discussion sur Twitter
  • Envoyer la discussion sur Google
  • Envoyer la discussion sur Facebook
  • Envoyer la discussion sur Digg
  • Envoyer la discussion sur Delicious
  • Envoyer la discussion sur MySpace
  • Envoyer la discussion sur Yahoo