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 :

Qu'est-ce que je n'ai pas compris dans les threads ?


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 Qu'est-ce que je n'ai pas compris dans les threads ?
    Bonjour,

    J'ai lu plusieurs articles sur les Threads. J'avais cru comprendre que lorsqu'un thread quitte sa méthode run il prend l'état TERMINATED.
    Aussi est-ce que quelqu'un peut m'expliquer ce qui ne marche pas dans le code suivant ?
    La classe interface graphique avec une méthode main(). On lance le thread avec le bouton play, on l'arrête avec le bouton stop (rien de bien original donc)
    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
     
    public class Essai extends JFrame  implements ActionListener, ObservateurFil
    {
    	private Fil monThread;
    	private JButton stop = new JButton("Stop") ;
    	private JButton play = new JButton("Play");
    	private boolean boucle = false;
     
    	public Essai ()
    	{
    		super("test Thread");
    		setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
    		monThread = new Fil();
    		monThread.ajouteObservateur(this);
    		JPanel boutons = new JPanel();
    		boutons.setLayout(new FlowLayout());
    		play.setEnabled(true);
    		stop.setEnabled(false);
    		play.addActionListener(this);
    		stop.addActionListener(this);
    		boutons.add(stop);
    		boutons.add(play);
    		this.add(boutons,BorderLayout.SOUTH);
    		pack();
    		setLocationRelativeTo(null);
    		setVisible(true);
    	}
     
    	@Override
    	public void actionPerformed(ActionEvent e) 
    	{
    		if (e.getSource() == stop) stop();
    		else if (e.getSource() == play) play();
    	}
     
    	private void play() 
    	{
    		System.out.println("j'ai cliqué sur play : " + monThread.getState());
    		if (monThread.getState() == State.TERMINATED) 
    		{
    			monThread = new Fil();
    		}
    		stop.setEnabled(true);
    		play.setEnabled(false);
    		monThread.setEtat(EtatFil.PLAY);
    		if (monThread.getState() == State.NEW) monThread.start();
    	}
     
    	private void stop() 
    	{
    		stop.setEnabled(false);
    		play.setEnabled(true);
    		monThread.setEtat(EtatFil.STOP);
    		System.out.println("fin du Thread " + monThread.getState());
    	}
     
    	@Override
    	public void finThread() 
    	{
    		stop();
    		if (boucle) play();
    	}
     
    	public static void main(String ...args) 
    	{
    		javax.swing.SwingUtilities.invokeLater(new Runnable() 
    	 	{
    			public void run() 
    	     	{
    				new Essai(); 
    	     	}
    	 	});
    	}
    }
    La classe qui représente un Thread. Au lancement du thread, on stocke l'heure de début du thread, puis on lance une boucle sans fin qui s'arrête soit par l'appui sur STOP soit parce que le temps est écoulé.
    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
     
    public class Fil  extends Thread
    {
    	private EtatFil etat;
    	private ObservateurFil observateur;
    	private List<ObservateurFil> observateurs = new ArrayList<ObservateurFil>();
     
    	public Fil()
    	{
    		super("Test Thread");
    		etat = EtatFil.STOP;
    	}
     
    	public void ajouteObservateur(ObservateurFil of)
    	{
    		this.observateur = of;
    	}
     
    	public void run()
    	{
    		long debut = System.currentTimeMillis();
    		int m = -1;
    		while(true)
    		{
    			if (etat == EtatFil.STOP || etat == EtatFil.EOM)
    			{
    				break;
    			}
    			if(etat == EtatFil.PLAY)
    			{
    				int t = (int) ((System.currentTimeMillis() - debut)/1000);
    				if (t != m) 
    				{
    					m = t;
    					System.out.println(m);
    				}
    				//on arrive à la fin du comptage, on arrête
    				if (m > 4)
    				{
    					etat = EtatFil.EOM;
    				}
    			}
    		}
    		observateur.finThread();
    	}
     
    	public void setEtat(EtatFil e) 
    	{
    		etat = e;
    	}
    }
    Une énumération des divers états du fil
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
     
    public enum EtatFil 
    {
        STOP, PAUSE , PLAY, EOM;
    }
    L'interface pour les observateurs
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
     
    public interface ObservateurFil 
    {
        public void finThread();
    }
    Quand je clique sur PLAY puis sur STOP j'ai cela dans la console.

    j'ai cliqué sur play : NEW
    0
    1
    2
    fin du Thread RUNNABLE
    fin du Thread RUNNABLE

    J'ai deux questions :
    pourquoi ai-je deux fois la ligne "fin du Thread RUNNABLE" ?
    pourquoi l'état n'est pas TERMINATED ?
    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
    Hello,

    Citation Envoyé par Patrice Henrio Voir le message
    Qu'est-ce que je n'ai pas compris dans les threads ?
    La synchronisation des données.

    Citation Envoyé par Patrice Henrio Voir le message
    pourquoi ai-je deux fois la ligne "fin du Thread RUNNABLE" ?
    Il est affiché à chaque fois que tu cliques sur le bouton et à chaque fois que le thread appelle finThread(), ce qui fait donc deux fois.
    C'est ton code, c'est toi qui l'as fait comme ça.

    Citation Envoyé par Patrice Henrio Voir le message
    pourquoi l'état n'est pas TERMINATED ?
    Le thread est toujours en plein dans sa méthode run(), dans les deux cas.
    Si tu avais utilisé la synchronisation et que donc ta tentative d'arrêter le thread marchait, il serait possible, bien que peu probable, que le deuxième affichage dise TERMINATED, le thread s'étant bel et bien terminé entre la demande d'arrêt et la demande de son état actuel.
    N'oubliez pas de consulter les FAQ Java et les cours et tutoriels Java

  3. #3
    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 Patrice Henrio Voir le message
    pourquoi ai-je deux fois la ligne "fin du Thread RUNNABLE" ?
    Parce que le code de la méthode stop() est exécuté deux fois.
    • Une fois via actionPerformed(), lorsque tu cliques sur le bouton.
    • Une fois via finThread() via l'observateur, lorsque le code du thread se termine.




    Citation Envoyé par Patrice Henrio Voir le message
    pourquoi l'état n'est pas TERMINATED ?
    Parce qu'il n'est pas encore terminé !

    Tu ne fais que changer un de ses attributs. Rien ne garantie que le code du thread est déjà fini...



    Sinon une remarque : Tu fais une boucle active pour attendre 1s !
    Un Thread.sleep() serait plus approprié... parce que sinon tu bouffes tout le CPU pour rien !


    a++

  4. #4
    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
    Tout d'abord merci de vos réponses.
    En tout premier lieu vous vous doutez bien que ce n'est qu'un modèle et que si je n'ai pas utilisé sleep(1000) pour attendre une seconde c'est que justement dans l'utilisation que je vais en faire je ne veux pas attendre une seconde sans rien faire. De plus sleep est entouré d'un try catch qui simplifie le problème car il me suffit alors d'appeler interrupt pour que ça marche comme je veux.

    Pour les deux appels j'aurai du en effet trouvé moi-même la raison. Ceci étant ce n'est pas bien grave car en définitive le but était seulement de trouver l'état dans lequel était le thread.

    Par contre pour la synchronisation ... c'est sûr que j'ai pas bien compris. J'ai pourtant lu plusieurs articles parlant de cela.

    Dans mon cas je pense que c'est etat qui devrait être synchronisé, mais je ne vois pas comment m'y prendre ?
    C'est en respectant les autres que l'on se fait respecter.

  5. #5
    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
    Citation Envoyé par Patrice Henrio Voir le message
    Par contre pour la synchronisation ... c'est sûr que j'ai pas bien compris. J'ai pourtant lu plusieurs articles parlant de cela.

    Dans mon cas je pense que c'est etat qui devrait être synchronisé, mais je ne vois pas comment m'y prendre ?
    Deux solutions :
    • Soit tu utilises des bloc synchronized à chaque fois que tu lis/modifies l'attribut "etat".
    • Soit tu le déclares en volatile, ce qui devrait être amplement suffisant...



    a++

  6. #6
    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
    Citation Envoyé par Patrice Henrio Voir le message
    car en définitive le but était seulement de trouver l'état dans lequel était le thread.
    Hummm... Pourquoi faire ?
    En principe c'est juste pour donner quelques infos de monitoring, c'est pas très important pour faire les choses elles-mêmes.
    N'oubliez pas de consulter les FAQ Java et les cours et tutoriels Java

  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
    Citation Envoyé par adiGuba Voir le message
    Deux solutions :
    • Soit tu utilises des bloc synchronized à chaque fois que tu lis/modifies l'attribut "etat".
    • Soit tu le déclares en volatile, ce qui devrait être amplement suffisant...



    a++
    J'ai donc essayé de déclarer etat en volatile mais ça n'a rien changé

    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
     
    public class Fil  extends Thread
    {
    	volatile EtatFil etat;
    	private ObservateurFil observateur;
    	// les écouteurs qui seront informés des changements d'état
    	private List<ObservateurFil> observateurs = new ArrayList<ObservateurFil>();
     
    	public Fil()
    	{
    		super("Test Thread");
    		etat = EtatFil.STOP;
    	}
     
    	public void ajouteObservateur(ObservateurFil of)
    	{
    		this.observateur = of;
    	}
     
    	/**
             * la boucle principale.
             * Actions selon l'état du lecteur
             */
    	public void run()
    	{
    		long debut = System.currentTimeMillis();
    		int m = -1;
    		while(true)
    		{
    			if (etat == EtatFil.STOP || etat == EtatFil.EOM)
    			{
    				break;
    			}
    			if(etat == EtatFil.PLAY)
    			{
    				int t = (int) ((System.currentTimeMillis() - debut)/1000);
    				if (t != m) 
    				{
    					m = t;
    					System.out.println(m);
    				}
    				//on arrive à la fin du comptage, on arrête
    				if (m > 4)
    				{
    					etat = EtatFil.EOM;
    				}
    			}
    		}
    		observateur.finThread(etat);
    	}
     
    	public void setEtat(EtatFil e) 
    	{
    		etat = e;
    	}
    }
    Et après un play/stop
    j'ai cliqué sur play : NEW
    0
    1
    fin du Thread RUNNABLE
    fin du Thread RUNNABLE

    Je vais tester la première solution
    C'est en respectant les autres que l'on se fait respecter.

  8. #8
    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
    Hummm... Pourquoi faire ?
    En principe c'est juste pour donner quelques infos de monitoring, c'est pas très important pour faire les choses elles-mêmes.
    Le but est d'avoir une interface qui gère un thread via deux boutons PLAY et STOP, mais le thread lui-même doit pouvoir communiquer avec l'interface soit pour recevoir les ordres de l'interface, soit pour indiquer à l'interface que le thread a fini son travail.
    C'est je pense un problème très classique mais je n'y arrive pas, ou plutôt je ne comprends pas tout. En effet dans l'exemple cité, si après STOP j'appuie de nouveau sur PLAY, le thread est bien dans l'état TERMINATED alors que le STOP indiquait un état RUNNABLE
    C'est en respectant les autres que l'on se fait respecter.

  9. #9
    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 adiGuba Voir le message
    Deux solutions :
    • Soit tu utilises des bloc synchronized à chaque fois que tu lis/modifies l'attribut "etat".
    • Soit tu le déclares en volatile, ce qui devrait être amplement suffisant...



    a++
    J'ai utilisé la première méthode avec synchronized, sans succès

    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
     
    public class Fil  extends Thread
    {
    	private EtatFil etat;
    	private ObservateurFil observateur;
    	// les écouteurs qui seront informés des changements d'état
    	private List<ObservateurFil> observateurs = new ArrayList<ObservateurFil>();
     
    	public Fil()
    	{
    		super("Test Thread");
    		etat = EtatFil.STOP;
    	}
     
    	public void ajouteObservateur(ObservateurFil of)
    	{
    		this.observateur = of;
    	}
     
    	/**
             * la boucle principale.
             * Actions selon l'état du lecteur
             */
    	public void run()
    	{
    		long debut = System.currentTimeMillis();
    		int m = -1;
    		while(true)
    		{
    			synchronized(etat)
    			{
    				if (etat == EtatFil.STOP || etat == EtatFil.EOM) break;
     
    				if(etat == EtatFil.PLAY)
    				{
    					int t = (int) ((System.currentTimeMillis() - debut)/1000);
    					if (t != m) 
    					{
    						m = t;
    						System.out.println(m);
    					}
    					//on arrive à la fin du comptage, on arrête
    					if (m > 4) etat = EtatFil.EOM;
    				}
    			}
    		}
    		observateur.finThread(etat);
    	}
     
    	public void setEtat(EtatFil e) 
    	{
    		etat = e;
    	}
    }
    Et toujours la même réponse :
    j'ai cliqué sur play : NEW
    0
    1
    2
    fin du Thread RUNNABLE
    fin du Thread RUNNABLE
    C'est en respectant les autres que l'on se fait respecter.

  10. #10
    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
    J'ai fini par régler le problème (presque).
    Tout venait effectivement, comme on me l'avait indiqué dés le début, du fait que par mon code je passais deux fois dans la méthode finThread().
    J'ai ainsi modifié ma classe Fil et ma classe Essai
    La classe Essai
    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
     
    public class Essai extends JFrame  implements ActionListener, ObservateurFil
    {
    	private Fil monThread;
    	private JButton stop = new JButton("Stop") ;
    	private JButton play = new JButton("Play");
    	private boolean boucle = false;
     
    	public Essai ()
    	{
    		super("test Thread");
    		setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
    		monThread = new Fil();
    		monThread.ajouteObservateur(this);
    		JPanel boutons = new JPanel();
    		boutons.setLayout(new FlowLayout());
    		play.setEnabled(true);
    		stop.setEnabled(false);
    		play.addActionListener(this);
    		stop.addActionListener(this);
    		boutons.add(stop);
    		boutons.add(play);
    		this.add(boutons,BorderLayout.SOUTH);
    		pack();
    		setLocationRelativeTo(null);
    		setVisible(true);
    	}
     
    	@Override
    	public void actionPerformed(ActionEvent e) 
    	{
    		if (e.getSource() == stop) stop();
    		else if (e.getSource() == play) play();
    	}
     
    	private void play() 
    	{
    		System.out.println("j'ai cliqué sur play : " + monThread.getState());
    		if (monThread.getState() == State.TERMINATED) 
    		{
    			monThread = new Fil();
    		}
    		stop.setEnabled(true);
    		play.setEnabled(false);
    		monThread.setEtat(EtatFil.PLAY);
    		if (monThread.getState() == State.NEW) monThread.start();
    	}
     
    	private void stop() 
    	{
    		stop.setEnabled(false);
    		play.setEnabled(true);
    		monThread.setEtat(EtatFil.STOP);
    		try 
    		{
    			Thread.sleep(200);
    		} catch (InterruptedException e) 
    		{
    			e.printStackTrace();
    		}
    		System.out.println("fin du Thread " + monThread.getState());
    	}
     
    	@Override
    	public void finThread() 
    	{
    		stop.setEnabled(false);
    		play.setEnabled(true);
    		try 
    		{
    			Thread.sleep(200);
    		} catch (InterruptedException e) 
    		{
    			e.printStackTrace();
    		}
     
    		System.out.println("fin du Thread " + monThread.getState());		
    		if (boucle) play();
    	}
     
    	public static void main(String ...args) 
    	{
    		javax.swing.SwingUtilities.invokeLater(new Runnable() 
    	 	{
    			public void run() 
    	     	{
    				new Essai(); 
    	     	}
    	 	});
    	}
     
    }
    Donc
    finThread() ne nécessite plus de passer un état.
    stop() attend 20 ms avant d'afficher l'état du thread ce qui doit lui laisser le temps de se terminer.
    La classe Fil
    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
     
    public class Fil  extends Thread
    {
    	private EtatFil etat;
    	private ObservateurFil observateur;
     
    	public Fil()
    	{
    		super("Test Thread");
    		etat = EtatFil.STOP;
    	}
     
    	public void ajouteObservateur(ObservateurFil of)
    	{
    		this.observateur = of;
    	}
     
    	public void run()
    	{
    		long debut = System.currentTimeMillis();
    		int m = -1;
    		while(true)
    		{
    				if (etat == EtatFil.STOP ) break;
     
    				if(etat == EtatFil.PLAY)
    				{
    					int t = (int) ((System.currentTimeMillis() - debut)/1000);
    					if (t != m) 
    					{
    						m = t;
    						System.out.println(m);
    					}
    					if (m > 4) 
    					{
    						observateur.finThread();
    						break;
    					}
    				}
    			}
    		}
    	}
     
    	public void setEtat(EtatFil e) 
    	{
    		etat = e;
    	}
    }
    Maintenant le STOP fonctionne comme je le souhaite par contre pour la fin du thread il y a un problème minime.
    A la fin du thread celui-ci est encore dans l'état RUNNABLE mais dés que je clique sur PLAY il se retrouve bien dans l'état TERMINATED
    C'est en respectant les autres que l'on se fait respecter.

  11. #11
    Expert éminent sénior
    Avatar de tchize_
    Homme Profil pro
    Ingénieur développement logiciels
    Inscrit en
    Avril 2007
    Messages
    25 481
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 44
    Localisation : Belgique

    Informations professionnelles :
    Activité : Ingénieur développement logiciels
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Avril 2007
    Messages : 25 481
    Points : 48 806
    Points
    48 806
    Par défaut
    Citation Envoyé par Patrice Henrio Voir le message
    A la fin du thread celui-ci est encore dans l'état RUNNABLE mais dés que je clique sur PLAY il se retrouve bien dans l'état TERMINATED
    En même temps, tu continue d'afficher

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    System.out.println("fin du Thread " + monThread.getState());
    dans finThread qui est appelé par le thread stocké dans monThread, qui tourne toujours donc. Forcément, son état est RUNNABLE, puisqu'il tourne toujours!!! (sinon comment pourrait-il appeler finThread hein)

    L'intérêt de la méthode Thread.getState, c'est d'être checkée par un autre thread, pas par le thread lui même, qui ne pourra jamais que répondre RUNNABLE

  12. #12
    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
    Citation Envoyé par Patrice Henrio Voir le message
    stop() attend 20 ms avant d'afficher l'état du thread ce qui doit lui laisser le temps de se terminer.
    Pour attendre qu'un thread se termine, il suffit d'appeler join() dessus.
    N'oubliez pas de consulter les FAQ Java et les cours et tutoriels Java

  13. #13
    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 tchize_ Voir le message
    En même temps, tu continue d'afficher

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    System.out.println("fin du Thread " + monThread.getState());
    dans finThread qui est appelé par le thread stocké dans monThread, qui tourne toujours donc. Forcément, son état est RUNNABLE, puisqu'il tourne toujours!!! (sinon comment pourrait-il appeler finThread hein)

    L'intérêt de la méthode Thread.getState, c'est d'être checkée par un autre thread, pas par le thread lui même, qui ne pourra jamais que répondre RUNNABLE
    Bon je comprends l'idée du finThread effectivement. Par contre le getState est bien checké dans le thread principal voir même ici dans l'EDT. Non ?
    C'est en respectant les autres que l'on se fait respecter.

  14. #14
    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
    Citation Envoyé par Patrice Henrio Voir le message
    Bon je comprends l'idée du finThread effectivement. Par contre le getState est bien checké dans le thread principal voir même ici dans l'EDT. Non ?
    Ouaip, il est donc possible que le thread soit fini à ce moment-là. Pas très probable par contre. L'ordonnanceur ne va pas passer son temps à faire du context switch, ça sert à rien.
    N'oubliez pas de consulter les FAQ Java et les cours et tutoriels Java

  15. #15
    Expert éminent sénior
    Avatar de tchize_
    Homme Profil pro
    Ingénieur développement logiciels
    Inscrit en
    Avril 2007
    Messages
    25 481
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 44
    Localisation : Belgique

    Informations professionnelles :
    Activité : Ingénieur développement logiciels
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Avril 2007
    Messages : 25 481
    Points : 48 806
    Points
    48 806
    Par défaut
    surtout, encore une fois, que la variable état n'est pas volatile, donc ca peux prendre TRES longtemps à avant que le thread n'utilise le nouvel état (voir potentiellement jamais).
    Dans le cas présent ton thread tourne comme un malade pendant 4 secondes. Il risque pas d'être vite délogé de son core et donc d'avoir une chance de sortir la donnée d'ailleurs que du cache du core

  16. #16
    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 tchize_ Voir le message
    surtout, encore une fois, que la variable état n'est pas volatile, donc ca peux prendre TRES longtemps à avant que le thread n'utilise le nouvel état (voir potentiellement jamais).
    Dans le cas présent ton thread tourne comme un malade pendant 4 secondes. Il risque pas d'être vite délogé de son core et donc d'avoir une chance de sortir la donnée d'ailleurs que du cache du core
    Même s'il y a quelques progrès par rapport à la version d'origine ce n'est pas encore ça.
    J'ai compris qu'en effet appeler la méthode finThread de la classe Essai ne pouvait pas renvoyer autre chose que RUNNABLE pour le thread puisqu'elle était appelée depuis le run() du thread.
    Là où cela se complique (et qui me montre bien que je n'ai toujours pas compris) c'est que si le booléen boucle est positionné à true il faut relancer le thread (en fait arrêter le thread précédent et en créer un nouveau avec les mêmes propriétés).
    Et là bien sûr ça marche pas.
    J'ai trois threads : main, EDT et Fil.
    EDT pilote Fil via les boutons, Fil doit envoyer à main une info indiquant la fin de son travail, si boucle = true on recommence !!!

    Dans la méthode run() je décompte le temps, lorsque j'arrive à 5 secondes je préviens l'observateur (une instance de la classe Essai) que le thread doit finir en appelant la méthode finThread() de Essai. Cette dernière méthode appelle stop() qui met fin au thread puis play() pour relancer. Mais comme finThread est appelée depuis le thread, celui-ci n'est pas terminé et ne peut donc se relancer.

    Je ne vois vraiment pas comment faire cela. Je vois bien que de la manière dont j'agis la méthode play() ne peut rien faire puisque le thread n'est pas terminé malgré l'appel à stop().

    J'ai déclaré etat comme variable volatile sans succès.
    C'est en respectant les autres que l'on se fait respecter.

  17. #17
    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
    Comme je l'ai déjà dit, pour attendre qu'un thread se termine, on fait join().

    Il pourrait aussi être intéressant de faire un thread qui boucle aussi longtemps que le programme tourne, et qui travaille quand on lui envoie du travail.
    N'oubliez pas de consulter les FAQ Java et les cours et tutoriels Java

  18. #18
    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
    J'ai fini par me poser la question : est-ce nécessaire que j'arrête mon Thread ?
    Finalement j'ai opté pour le laisser se terminer tout seul.
    Donc lorsque le thread a tourné pendant 5 secondes, j'appelle finThread de la classe Essai qui positionne un booléen fini à true puis (si boucle vaut true) rappelle play(). Dans cette dernière méthode si le thread est dans l'état TERMINATED ou si le booléen fini est à true, je recrée un nouveau Thread et le lance. Un affichage des Threads actifs m'indique si mon nombre de threads gonfle, ce qui n'est pas le cas.

    Est-ce correct de faire ainsi ?
    C'est en respectant les autres que l'on se fait respecter.

  19. #19
    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
    Comme je l'ai déjà dit, pour attendre qu'un thread se termine, on fait join().

    Il pourrait aussi être intéressant de faire un thread qui boucle aussi longtemps que le programme tourne, et qui travaille quand on lui envoie du travail.
    Oui ça serait pas mal. Mais je ne vois pas du tout comment faire.
    En fait tout ces problèmes viennent d'un lecteur MP3 simplifié que j'ai créé (à partir du code source de Javazoom). Ca fonctionne très bien sous Windows mais sous Ubuntu j'avais un problème qui venait en fait de ce que l'installation de openJDK entraîne l'installation de Icedtea qui lui même installe son propre pilote audio. J'ai résolu ce premier problème et ensuite dans les tests (Windows ou Ubuntu) je me suis aperçu que parfois le programme plantait, plus exactement une exception était levée avec affichage sur la console mais le programme continuait comme si de rien n'était. Comme je suis un perfectionniste j'ai voulu corriger ce problème. Et là je me suis aperçu que j'avais été trop servile vis à vis du code de Javazoom et qu'une partie de ce que j'avais copié paraissait inutile et entraînait même des situations problématiques.
    En résumé plutôt tous mes problèmes viennent surtout de ce que je n'ai pas encore assimilé les Thread et les problèmes de synchronisation.
    C'est en respectant les autres que l'on se fait respecter.

  20. #20
    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
    Citation Envoyé par Patrice Henrio Voir le message
    Est-ce correct de faire ainsi ?
    Ca dépend de ce que tu veux faire...

    Jusqu'à présent tu ne parles que du coté technique et de la manière dont tu fais... mais on ne sait toujours pas quel est l'objectif de tout cela.


    Bref : Que cherches-tu à faire ?

    a++

+ Répondre à la discussion
Cette discussion est résolue.
Page 1 sur 2 12 DernièreDernière

Discussions similaires

  1. [Smarty] Pourquoi le php n'est pas recommandé dans les templates ?
    Par SlymDesign dans le forum Bibliothèques et frameworks
    Réponses: 5
    Dernier message: 10/10/2007, 11h21
  2. Est-ce que je peux utiliser certain symbole dans le nom de dossier
    Par pierrot10 dans le forum Balisage (X)HTML et validation W3C
    Réponses: 2
    Dernier message: 24/09/2007, 20h45
  3. [DOM] Qu'est-ce que IE7 ne comprend pas ?
    Par MikeV dans le forum Général JavaScript
    Réponses: 5
    Dernier message: 14/08/2007, 22h38
  4. Réponses: 3
    Dernier message: 26/04/2007, 11h50
  5. qu'est ce que vous n'accepterez pas de votre boss ?
    Par gloglo dans le forum Emploi
    Réponses: 13
    Dernier message: 22/11/2006, 00h48

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