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 :

Problèmes sur les Threads (acte 2)


Sujet :

Concurrence et multi-thread Java

  1. #1
    Membre averti

    Profil pro
    Inscrit en
    Janvier 2004
    Messages
    464
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Janvier 2004
    Messages : 464
    Points : 332
    Points
    332
    Par défaut Problèmes sur les Threads (acte 2)
    J'ai rajouté une barre de progression pour mon porgramme.
    Donc :
    Une interface graphique : une barre de progression (0 à 100) et en dessous trois boutons play, pause, stop. La barre de progression indique visuellement la progression du travail d'un Thread. L'appui sur play lance le travail, l'appui sur pause arrête le travail un appui sur play reprend là où il était, l'appui sur stop arrête le travail un appui sur play reprend au début. Lorsque le travail du thread est terminé soit on arrête soit on reprend du début suivant la valeur d'un booléen boucle.
    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
    108
    109
    110
    111
    112
    113
    114
    115
    116
    117
    118
     
    public class Fenetre extends JFrame implements ActionListener, ObservateurLecteur
    {
    	private MonThread monThread;
    	JButton stop = new JButton("Stop") ;
    	JButton pause = new JButton("Pause");
    	JButton play = new JButton("Play");
     
    	private JProgressBar progression = new JProgressBar(0,100);
     
    	private boolean boucle = false;
    	private boolean fini = false;
     
    	public Fenetre ()
    	{
    		super("MonThread");
    		setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
    		monThread = new MonThread(this);
     
    		/** Construction de la fenêtre *******/
    		this.progression.setMaximum(100);
    		this.add(this.progression,BorderLayout.NORTH);
    		JPanel boutons = new JPanel();
    		boutons.setLayout(new FlowLayout());
     
    		// au début play est seul actif
    		play.setEnabled(true);
    		stop.setEnabled(false);
    		pause.setEnabled(false);
    		play.addActionListener(this);
    		stop.addActionListener(this);
    		pause.addActionListener(this);
    		boutons.add(play);
    		boutons.add(pause);
    		boutons.add(stop);
    		this.add(boutons,BorderLayout.SOUTH);
    		pack();
    		setLocationRelativeTo(null);
    		setVisible(true);
    		monThread.start();
    	}
     
    	  public static void main(String ...args) 
    	  {
    		    javax.swing.SwingUtilities.invokeLater(new Runnable() 
    	        {
    				public void run() 
    	            {
    					new Fenetre(); 
    	            }
    	        });
    	  }
     
    	@Override
    	public void actionPerformed(ActionEvent e) 
    	{
    		if (e.getSource() == stop) stop();
    		else if (e.getSource() == play) play();
    		else if (e.getSource() == pause) pause();
    	}
     
    	private void pause() 
    	{
    		pause.setEnabled(false);
    		stop.setEnabled(true);
    		play.setEnabled(true);
    		monThread.setEtat(Etat.PAUSE);
    	}
     
    	private void play() 
    	{
    		if (fini)
    		{
    			monThread.setDebut(0);
    			fini = false;
    		}
    		stop.setEnabled(true);
    		pause.setEnabled(true);
    		play.setEnabled(false);
    		monThread.setEtat(Etat.PLAY);
    	}
     
    	private void stop() 
    	{
    		fini = true;
    		stop.setEnabled(false);
    		pause.setEnabled(false);
    		play.setEnabled(true);
    		monThread.setEtat(Etat.STOP);
    		progression(0);
    	}
     
    	@Override
    	public void finLecture() 
    	{
    		fini = true;
    		if (boucle) play();
    		else stop();
    	}
     
    	@Override
    	public void progression(final int v) 
    	{
    	    SwingUtilities.invokeLater(new Runnable() 
    	    {
    	        public void run() 
    	        {
    	            Fenetre.this.progression.setValue(v) ;
    	        }
    	    });
    	}
     
    	@Override
    	public void definirDuree(int max) 
    	{
    		this.progression.setMaximum(max);
    	}
    }
    La classe 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
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    49
    50
    51
    52
    53
     
    public class MonThread extends Thread
    {
    	private ObservateurLecteur observateur;
    	private volatile Etat etat;
    	private volatile int debut = -1;
     
     
    	public MonThread(ObservateurLecteur ol)
    	{
    		super("MonThread");
    		this.observateur = ol;
    		etat = Etat.STOP;
    	}
     
    	public void setDebut(int x)
    	{
    		debut = x;
    	}
     
    	/**
             * la boucle principale
             */
    	public void run()
    	{
    		while(true)
    		{
    			if(etat == Etat.PLAY)
    			{
    				debut += 10;
     
    				try 
    				{
    					Thread.sleep(500);
    				} 
    				catch (InterruptedException e) 
    				{
    					e.printStackTrace();
    				}
    				if ( debut <= 100)
                	{
                      	observateur.progression(debut);
                	}
                	else observateur.finLecture();
    			}
    		}
    	}
     
    	public void setEtat(Etat e) 
    	{
    		etat = e;
    	}
    }
    Tout marche correctement à un détail près.
    Lorsque je clique sur stop la barre de progression s'affiche avec la valeur à laquelle on était rendu et non pas avec une valeur nulle malgré la ligne progression(0) qui doit mettre la valeur de cette barre à 0.
    C'est en respectant les autres que l'on se fait respecter.

  2. #2
    Modérateur

    Profil pro
    Inscrit en
    Septembre 2004
    Messages
    12 551
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Septembre 2004
    Messages : 12 551
    Points : 21 607
    Points
    21 607
    Par défaut
    Les probabilités sont énormes que observateur.progression(debut); s'exécute après progression(0);, annulant donc son effet.
    N'oubliez pas de consulter les FAQ Java et les cours et tutoriels Java

  3. #3
    Membre averti

    Profil pro
    Inscrit en
    Janvier 2004
    Messages
    464
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Janvier 2004
    Messages : 464
    Points : 332
    Points
    332
    Par défaut
    Citation Envoyé par thelvin Voir le message
    Les probabilités sont énormes que observateur.progression(debut); s'exécute après progression(0);, annulant donc son effet.
    En effet j'aurai du m'en douter. Il me reste à trouver comment éviter cela : c'est typiquement un problème de Thread.

    En fait il suffit de recontrôler la valeur de la variable etat.
    C'est en respectant les autres que l'on se fait respecter.

  4. #4
    Modérateur

    Profil pro
    Inscrit en
    Septembre 2004
    Messages
    12 551
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Septembre 2004
    Messages : 12 551
    Points : 21 607
    Points
    21 607
    Par défaut
    Il commence à être temps de songer à faire des accès exclusifs avec synchronized. Mais pour l'instant une simple vérification de la variable est suffisante en pratique.
    N'oubliez pas de consulter les FAQ Java et les cours et tutoriels Java

  5. #5
    Membre averti

    Profil pro
    Inscrit en
    Janvier 2004
    Messages
    464
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Janvier 2004
    Messages : 464
    Points : 332
    Points
    332
    Par défaut
    Citation Envoyé par thelvin Voir le message
    Il commence à être temps de songer à faire des accès exclusifs avec synchronized. Mais pour l'instant une simple vérification de la variable est suffisante en pratique.
    J'ai pas bien compris comment faire. Peux-tu me dire sur cet exemple comment tu ferais pour ce fameux synchronized ?
    Pourtant de la doc sur ce sujet j'en ai lu un paquet, mais ça veut pas rentrer.
    C'est en respectant les autres que l'on se fait respecter.

  6. #6
    Membre averti

    Profil pro
    Inscrit en
    Janvier 2004
    Messages
    464
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Janvier 2004
    Messages : 464
    Points : 332
    Points
    332
    Par défaut
    Donc si j'ai bien compris la situation, mon programme utilise 3 threads : main, EDT et monThread.
    monThread tourne pendant toute la durée du programme via sa méthode redéfinie run qui est lancée par l'appel à monThread.start();
    EDT surveille les clics sur les boutons.

    L'attribut etat de la classe MonThread peut prendre trois valeurs, PLAY, PAUSE, STOP et est commandée par les boutons. Seule l'instance de Fenetre peut modifier cette variable.
    La variable observateur représente l'interface graphique, instance de Fenetre.
    La variable debut de la classe MonThread est augmentée de 10 régulièrement. Lorsqu'elle dépasse 100 on appelle la méthode finThread de l'attribut observateur qui suivant la valeur d'un booléen reprend la travail à 0 ou arrête :
    Reprendre à 0 signifie simplement donner respectivement la valeur 0 et PLAY aux attributs debut et etat de monThread, ce qui a pour conséquence de relancer l'animation de la barre de progression.
    Arrêter signifie simplement passer l'attribut etat à STOP.
    Où dois-je mettre la synchronisation : autour du while, autour de chaque bloc utilisant etat, dans la classe MonThread, dans la classe Fenetre, sur les méthodes utilisant etat, debut ?
    Dans la boucle while(true) de la méthode run, je ne fais quelque chose que si etat vaut PLAY. Mais lorsque je clique sur STOP, un certain nombre d'opération se font et en particulier la valeur de la barre de progression est placée à 0. Mais monThread reprend la main et termine son travail d'où la nécessité de revérifier que etat vaut bien PLAY pour redessiner la barre de progression. Je voudrai me débarasser de ce test et j'ai cru comprendre qu'un synchronized judicieusement placé permettrait cela.
    C'est en respectant les autres que l'on se fait respecter.

  7. #7
    Membre averti

    Profil pro
    Inscrit en
    Janvier 2004
    Messages
    464
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Janvier 2004
    Messages : 464
    Points : 332
    Points
    332
    Par défaut
    A force de réfléchir et de relire la documentation j'ai fini par comprendre comment faire.

    La variable à synchroniser est la variable etat qui doit être synchronisée avant de rentrer dans le test de sa valeur et ainsi il n'est plus nécessaire de la déclarer comme volatile.
    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
     
    public class MonThread extends Thread
    {
    	private ObservateurLecteur observateur;
    	private /*volatile*/ Etat etat;
    	private /*volatile*/ int debut = 0;
     
     
    	public MonThread(ObservateurLecteur ol)
    	{
    		super("MonThread");
    		this.observateur = ol;
    		etat = Etat.STOP;
    	}
     
    	public void setDebut(int x)
    	{
    		debut = x;
    	}
     
    	/**
             * la boucle principale
             */
    	public void run()
    	{
    		while(true)
    		{
    			synchronized(etat)
    			{
    				if(etat == Etat.PLAY)
    				{
    					debut += 10;
    					if ( debut <= 100)
    	            	{
    	                  	observateur.progression(debut);
    	                  	try 
    						{
    							Thread.sleep(500);
    						} 
    						catch (InterruptedException e) 
    						{
    							e.printStackTrace();
    						}
    	            	}
    	            	else observateur.finLecture();
    				}
    			}
    		}
    	}
     
    	public void setEtat(Etat e)
    	{
    		etat = e;
    	}
    }
    C'est en respectant les autres que l'on se fait respecter.

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

Discussions similaires

  1. problème sur les threads et les sémaphores
    Par ramislebob dans le forum Windows
    Réponses: 1
    Dernier message: 29/06/2006, 11h52
  2. Question sur les threads
    Par nicolas66 dans le forum MFC
    Réponses: 4
    Dernier message: 03/06/2005, 20h57
  3. Réponses: 5
    Dernier message: 10/05/2005, 10h22
  4. Aide sur les Threads
    Par themoye dans le forum MFC
    Réponses: 24
    Dernier message: 06/03/2005, 15h02
  5. Question simple sur les threads :)
    Par momox dans le forum C++Builder
    Réponses: 2
    Dernier message: 15/06/2003, 04h13

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