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

  1. #1
    Futur Membre du Club
    Homme Profil pro
    Étudiant
    Inscrit en
    Mai 2013
    Messages
    12
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France

    Informations professionnelles :
    Activité : Étudiant

    Informations forums :
    Inscription : Mai 2013
    Messages : 12
    Points : 7
    Points
    7
    Par défaut Problème impliquant de l'objet et des Threads mais étant trop compliqué à résumer dans un titre succin
    tout d'abord, Bonjour moi c'est az-steak! (comme c'est subtilement indiqué dans le post)
    Trève de présentation, j'explique mon problème.

    Alors voilà, j'ai depuis quelque mois un petit problème que voici :

    Je code une application java utilisant Opengl. J'utilise, afin de déplacer la caméra, un objet et un Thread dont voici les rôles:
    • L'objet a plusieurs paramètres booléens qui changent selon si une touche du clavier est pressée ou non
    • et le Thread lit ces valeur et déplace ma caméra en conséquence


    Le problème vient de mon thread qui ressemble à ça

    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
    public class SmoothKeyListener extends Thread{
     
    	opengl dessin;
    	Clavier input;
    	float speed=0.00001f;
    	boolean loop = true;
     
    	SmoothKeyListener(opengl dessin,Clavier input){
    		this.dessin = dessin;
    		this.input = input;
    	}
     
    	public void run(){
    		while(loop){
    			if(input.forward){
    				dessin.deplacerCam(0,0,speed);
    			}
    			if(input.backward){
    				dessin.deplacerCam(0,0,-speed);
    			}
    			if(input.left){
    				dessin.deplacerCam(speed,0,0); 
    			}
    			if(input.right){
    				dessin.deplacerCam(-speed,0,0);
    			}
    		}
    	}
    }
    SAUF QUE, le thread ne détecte jamais de changement et n'entre jamais dans une des conditions.
    On pourrais penser que le problème vient de ma classe Clavier SAUF QUE, comme je l'ai dis j'ai ce problème depuis quelques mois et j'utilisais jusque là une solution provisoire que voici (attention la nuance est subtile les amis!)

    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
    public class SmoothKeyListener extends Thread{
     
    	opengl dessin;
    	Clavier input;
    	float speed=0.00001f;
    	boolean loop = true;
     
    	SmoothKeyListener(opengl dessin,Clavier input){
    		this.dessin = dessin;
    		this.input = input;
    	}
     
    	public void run(){
    		while(loop){
                            System.out.println(input.forward); /////// la différence est juste là!!
    			if(input.forward){
    				dessin.deplacerCam(0,0,speed);
    			}
    			if(input.backward){
    				dessin.deplacerCam(0,0,-speed);
    			}
    			if(input.left){
    				dessin.deplacerCam(speed,0,0); 
    			}
    			if(input.right){
    				dessin.deplacerCam(-speed,0,0);
    			}
    		}
    	}
    }
    Et là, ça fonctionne!
    Je sais bien que cette solution n'est pas cool, mais même après d'infructueuses recherches et m'être frappé l'occiput à multiples reprises je n'ai jamais pu trouver de meilleure solution.

    Le problème de cette solution est que cela ralentit considérablement mon thread de faire un print à chaque itération et de fait le mouvement de la caméra est saccadé.
    J'implore donc votre aide afin de savoir si quelqu'un a déjà vu ce genre de problème et/ou pourrais aider à trouver une solution.

  2. #2
    Modérateur
    Avatar de wax78
    Homme Profil pro
    Chef programmeur
    Inscrit en
    Août 2006
    Messages
    4 074
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 43
    Localisation : Belgique

    Informations professionnelles :
    Activité : Chef programmeur
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Août 2006
    Messages : 4 074
    Points : 7 978
    Points
    7 978
    Par défaut
    C'est effectivement très bizarre en effet et je ne vois pas.

    Par contre, faire tourner un Thread ainsi sans mettre une petite pause ou quelques chose, je ne suis pas sur que ca soit la meilleur des idées.
    (Les "ça ne marche pas", même écrits sans faute(s), vous porteront discrédit ad vitam æternam et malheur pendant 7 ans)

    N'oubliez pas de consulter les FAQ Java et les cours et tutoriels Java

  3. #3
    Futur Membre du Club
    Homme Profil pro
    Étudiant
    Inscrit en
    Mai 2013
    Messages
    12
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France

    Informations professionnelles :
    Activité : Étudiant

    Informations forums :
    Inscription : Mai 2013
    Messages : 12
    Points : 7
    Points
    7
    Par défaut
    Citation Envoyé par wax78 Voir le message

    Par contre, faire tourner un Thread ainsi sans mettre une petite pause ou quelques chose, je ne suis pas sur que ca soit la meilleur des idées.
    Ah? sur le moment ça m'a semblé être une bonne idée xD

  4. #4
    Futur Membre du Club
    Homme Profil pro
    Étudiant
    Inscrit en
    Mai 2013
    Messages
    12
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France

    Informations professionnelles :
    Activité : Étudiant

    Informations forums :
    Inscription : Mai 2013
    Messages : 12
    Points : 7
    Points
    7
    Par défaut
    Un système d'évènement? Ça ne me dit rien, à la base on faisait un simple listener en cours de 3d, mais le résultat était pas terrible, ça saccadait, donc j'ai utiliser le système de Thread, faute de mieux.

  5. #5
    Modérateur
    Avatar de wax78
    Homme Profil pro
    Chef programmeur
    Inscrit en
    Août 2006
    Messages
    4 074
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 43
    Localisation : Belgique

    Informations professionnelles :
    Activité : Chef programmeur
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Août 2006
    Messages : 4 074
    Points : 7 978
    Points
    7 978
    Par défaut
    Oublies le message précédent.

    Tu devrais essayer quand même de mettre une petite pause quand même histoire de voire par curiosité (10 ms par exemple ou cas ou tu veux quand même une faible latence entre les différence d'entrée et le comportement de ta camera ?).
    (Les "ça ne marche pas", même écrits sans faute(s), vous porteront discrédit ad vitam æternam et malheur pendant 7 ans)

    N'oubliez pas de consulter les FAQ Java et les cours et tutoriels Java

  6. #6
    Futur Membre du Club
    Homme Profil pro
    Étudiant
    Inscrit en
    Mai 2013
    Messages
    12
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France

    Informations professionnelles :
    Activité : Étudiant

    Informations forums :
    Inscription : Mai 2013
    Messages : 12
    Points : 7
    Points
    7
    Par défaut
    Oh, ça fonctionne! Je n'ai aucune idée du pourquoi mais merci beaucoup!
    De plus, avec une petite pause on ne remarque pas de saccade, c'est parfait.

    Une explication à ce phénomène mystique?

  7. #7
    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
    Que ce soit system.out.println ou Thread.sleep, je suppose que ces deux méthodes font appel quelque part à une méthode synchronisée, ce qui invalide le cache du Thread. Je suppose que tes champs de ta classe clavier n'ont pas été défini à volatil, ce qui fait que la jvm le met en cache dans le thread pour des raisons de perfs et ne remarque pas qu'un autre thread a modifié les valeur.

  8. #8
    Futur Membre du Club
    Homme Profil pro
    Étudiant
    Inscrit en
    Mai 2013
    Messages
    12
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France

    Informations professionnelles :
    Activité : Étudiant

    Informations forums :
    Inscription : Mai 2013
    Messages : 12
    Points : 7
    Points
    7
    Par défaut
    En effet je n'ai rien défini de volatil (ne connaissant pas ça tout simplement!)

  9. #9
    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,


    Pour l'explication : lorsque tu partages un variable entre deux threads, il faut impérativement mettre en place un mécanisme de synchronisation.
    En effet la JVM peut optimiser l'accès à la mémoire, en recopiant la variable dans le cache du CPU pour de meilleure performance.

    Du coup avec 2 threads la variable peut être stocké dans 3 emplacements :
    • Dans la mémoire globale géré par le Garbage Collector (la RAM).
    • Dans le cache du CPU sur lequel s'exécute le thread 1
    • Dans le cache du CPU sur lequel s'exécute le thread 2



    Lorsqu'un thread modifie la valeur de la variable, elle la modifie dans son cache et dans la mémoire globale... mais pas dans le cache des autres threads.

    Pour que le cache d'un thread soit mis à jour, il faut une opération de synchronisation (comme System.out.println()) ou un réveil du thread (après le sleep).

    Toutefois perso je ne me baserais pas trop là dessus, car ce n'est pas lié aux variables en question.
    Je n'ai plus en tête les règles exacts, mais il est possible que dans certaines conditions tes variables ne soient pas mises à jour.


    La solution la plus simple consiste à déclarer en volatile les attributs forward, backward, left, et right de ta classe Clavier.
    volatile indique à la JVM que la variable est potentiellement manipulé par d'autres threads, ce qui va forcer une lecture de sa valeur réelle.


    Au passage tu risques d'avoir le même genre de problème avec ta variable loop de ton thread...


    a++


    PS : Par contre je conserverait le sleep() pour éviter de trop boucler et de bouffer du CPU pour rien.
    Avec 10ms cela fait sûrement 100 itérations par secondes, ce qui doit être amplement suffisant pour un affichage...
    Ou alors tu peux utiliser un Timer à la place de ton thread

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

Discussions similaires

  1. Réponses: 9
    Dernier message: 09/10/2010, 02h51
  2. Réponses: 4
    Dernier message: 21/02/2007, 17h08
  3. Problème avec des threads
    Par rajuto dans le forum Concurrence et multi-thread
    Réponses: 8
    Dernier message: 11/02/2007, 20h41
  4. [WD9] Problème avec l'utilisation des threads
    Par ramaro dans le forum WinDev
    Réponses: 2
    Dernier message: 29/01/2007, 11h51

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