Partage
  • Partager sur Facebook
  • Partager sur Twitter

La synchronisation, cette galère

    27 août 2016 à 10:53:39

    Bonjour,

    J'ai un problème que des heures et des heures d'essais et de jurons n'ont toujours pas réussi à résoudre. J'ai la chose suivante : 

    public void afficherCoup(){
    
       maj();
       pause();
    }



    où maj() est une fonction qui actualise mon affichage et fait appel à plusieurs paintComponent() de manière automatique, et pause() est une simple fonction de pause à base de Thread.sleep(). Les deux fonctions sont définies en synchronized.

    Mon problème est le suivant : la pause commence bien à s'exécuter après que la fonction maj() est terminée comme des tests le montrent bien, le hic, c'est que l'affichage n'est pas encore mis à jour à ce moment là.

    J'ai l'impression d'avoir tout essayé, avec des wait(), des notify(), des Executor, à peu près tout ce qui m'est venu à l'esprit, mais rien n'y fait...

    Est-il possible de mettre un bout de code en attente jusqu'à ce que l'affichage soit complètement actualisé ?

    Il y a clairement un truc que je n'ai pas compris avec ces gestions de la synchronisation, mais là je n'y arrive plus tout seul. Merci à toute personne qui pourra m'aider.

    Cordialement

    Paf

    -
    Edité par PafLeChien 27 août 2016 à 10:57:10

    • Partager sur Facebook
    • Partager sur Twitter
      28 août 2016 à 9:52:31

      Hello,

      tu as combien de thread? tu parles de synchronisation mais jamais de thread, ce qui est assez étrange

      peux tu montrer plus de code? notamment ta fonction de mise à jour  de l'IHM?

      • Partager sur Facebook
      • Partager sur Twitter
        28 août 2016 à 12:42:37

        J'ai plusieurs threads au niveau graphique (mise à jour de composants), et c'est bien ceux-là que j'aimerais réguler.

        En fait, il s'agit d'un petit jeu avec une IA (de l'Awale, un jeu africain) où un coup est une succession de déplacements de pierres, et le souci est que chaque coup s'affiche de manière instantané. Comme la gestion des coups se fait dans une seule fonction, je souhaiterais mettre des pauses après chaque "partie de coup", le seul souci étant que toutes les pauses se regroupent à la fin de la séquence. Donc j'aimerais synchroniser la fonction de pause pour que cette dernière s'exécute uniquement lorsque l'affichage est terminé. Voilà, j'espère que c'est clair, je vais essayer de mettre un peu de code mais comme c'est déjà assez conséquent, ce n'est pas facile de trier.

        La fonction de pause toute bête :

        public synchronized void pause(){
                try{
        		Thread.sleep(VITESSE_AFFICHAGE);
        	}catch(Exception e){
        			
        	}
        }

        La fonction de mise à jour des composants, elle fait appel à des paintComponent(). La fenêtre est composée de deux greniers aux extrémités (des JPanel) et d'un JPanel central coupé en 12 cases dans lesquelles sont les pierres.

        public synchronized void maj(){
        	for(int i=0;i<12;i++){
        		cellules[i].contenu= moteur.position[i];
        		cellules[i].label.setText(""+ moteur.position[i]);
        	}
        	grenier1.label.setText(""+moteur.piecesCaptureesj2);
        	grenier2.label.setText(""+moteur.piecesCaptureesj1);
        }

        Et la fonction qui met à jour l'affichage une fois un coup choisi : (la variable moteur est une instance de l'IA

        public void afficherCoup(int coup){
        	int caseCourante=coup;
        	int pierres=moteur.position[coup];
        	moteur.position[coup]=0; 
        	maj();
        	pause();
        		
        	do{
        		caseCourante=(caseCourante+1)%12;
        		if(caseCourante!=coup){
        			moteur.position[caseCourante]++;
        			pierres--;
        			maj();
        			pause();
        		}
        	}while(pierres>0);
        	if(moteur.trait==1){
        		while((moteur.position[caseCourante]==2||moteur.position[caseCourante]==3)&&
        					(caseCourante>5&&caseCourante<12)){
        				
        			moteur.piecesCaptureesj1+=moteur.position[caseCourante];
        			moteur.position[caseCourante]= 0;
        			caseCourante =(caseCourante-1)%12;
        			maj();
        			pause();
        		}
        	}else{
        		while((moteur.position[caseCourante]==2||moteur.position[caseCourante]==3)&&
        					(caseCourante<6)){
        				
        			moteur.piecesCaptureesj2+=moteur.position[caseCourante];
        			moteur.position[caseCourante]= 0;
        			caseCourante =(caseCourante-1)%12;
        			maj();
        			pause();
        				
        			if(caseCourante==-1){
        				caseCourante=11;
        			}
        		}
        	}
        	moteur.trait=-moteur.trait; 	
        }

        J'espère que c'est à peu près clair, le problème n'est pas simple à résumer. Merci d'avance.


        -
        Edité par PafLeChien 28 août 2016 à 12:43:02

        • Partager sur Facebook
        • Partager sur Twitter
          28 août 2016 à 14:11:49

          Je comprends un peu mieux mais il reste encore des points sombres.

          Je ne vois pas l'interet de stoper le thread de l'affichage.

          Pour moi, tu as 2 threads , l'affichage et le code métier. Lors de la création de l'affichage, tu lui attaches des elements du metier (généralement avec le pattern observer).

          Comme cela, tu définis un taux de rafraichissement de la vue, indépendant de ce qui se passe dans le métier.

          Si d'autres personnes ont une vision différente, je suis preneur, j'ai fait ce genre de chose en C++ et non en Java

          • Partager sur Facebook
          • Partager sur Twitter
            28 août 2016 à 15:07:09

            Je veux mettre à jour l'affichage en plusieurs fois. En gros, un coup est le vidage d'une case et le dépôt d'une pierre dans les cases suivantes. Si absolument tout se fait instantanément, on n'y voit rien. Ce qui se passe actuellement avec un temps de pose de 0.3 secondes avec une dépose sur 3 cases :

            1.2 secondes de latence --> Vidage de la case --> Dépot1 --> Dépot 2--> --> Dépot3, donc la pause est au début et tout se met à jour en une seule fois.

            Ce que j'aimerais 

            Vidage de la case --> 0.3 secondes de latence -->Dépot 1 --> 0.3 secondes de latence ... et ainsi de suite

            Le problème est que le calcul du coup est procédural, et l'affichage un thread. J'arrive pas à combiner le tout pour faire ce que je veux.

            • Partager sur Facebook
            • Partager sur Twitter
              28 août 2016 à 18:30:54

              quel thread  appelle maj et pause?
              • Partager sur Facebook
              • Partager sur Twitter
                28 août 2016 à 21:33:02

                Aucun. Elles sont appelées dans la fonction qui affiche un coup une fois sélectionné par l'IA.
                • Partager sur Facebook
                • Partager sur Twitter

                La synchronisation, cette galère

                × Après avoir cliqué sur "Répondre" vous serez invité à vous connecter pour que votre message soit publié.
                × Attention, ce sujet est très ancien. Le déterrer n'est pas forcément approprié. Nous te conseillons de créer un nouveau sujet pour poser ta question.
                • Editeur
                • Markdown