Attendre la fin d'exécution d'une méthode [Résolu]

Sphaxounet0 20 Messages postés mardi 30 mars 2010Date d'inscription 27 avril 2012 Dernière intervention - 25 avril 2012 à 12:44 - Dernière réponse :  sanfujinkai
- 21 juin 2016 à 15:02
Bonjour,

Je ne parviens pas à faire en sorte qu'une fonction attende la fin de l'exécution de la précédente. Je m'explique.

try{
   fonctionQuiCrééUnFichier();//Cette fonction s'exécute rapidement mais le fichier créé n'est utilisable qu'au bout de 4,5 secondes.
   fonctionQuiUtiliseLeFichier();
}catch{..}


Je veux donc faire patienter l'utilisateur pendant les 4,5 secondes. Alors j'utilise Thread.sleep(4500);
Parallèlement à cette attente, j'aimerai utiliser une barre de progression pour que ce soit plus agréable pour l'utilisateur(j'utilise celle de GillesWebmaster qui est parfaite pour ce dont j'ai besoin : http://www.javafr.com/codes/EXEMPLE-UTILISATION-JPROGRESSBAR-BARRE-PROGRESSION_36496.aspx )

try{
   fonctionQuiCrééUnFichier();//Cette fonction s'exécute rapidement mais le fichier créé n'est utilisable qu'au bout de 4,5 secondes.
   barreProgress.lancementProgression();//Dure 4,5 secondes.
   Thread.sleep(4500);
   fonctionQuiUtiliseLeFichier();
}catch{..}


Le problème c'est que le sleep() freeze tout (y compris la visualisation de la barre de progression).
J'aimerai donc retirer le Thread.sleep() et faire en sorte que fonctionQuiUtiliseLeFichier() ne s'exécute QU'UNE FOIS QUE lancementProgression() est terminée.

Il semblerait que wait()/notify() puisse aider, mais je ne vois pas comment, ou mettre en place des sémaphores, ou utiliser une queue. Mais il me semble que ces 2 dernières méthodes sont un peu lourdes pour mon simple problème non ?

Merci d'avance !
Afficher la suite 

Votre réponse

19 réponses

Meilleure réponse
cs_Julien39 6450 Messages postés mardi 8 mars 2005Date d'inscription 17 mai 2018 Dernière intervention - 25 avril 2012 à 13:54
3
Merci
Salut,

Tu n'y arrives pas parce que tu n'utilises pas les threads :

try{
   final Thread t1 = new Thread(){
      @Override
      public void run(){
         fonctionQuiCrééUnFichier();
      }
   };
   t1.start();
   new Thread(){
      @Override
      public void run(){
         t1.join();
         fonctionQuiUtiliseLeFichier();
      }
   }
}catch{..}

Merci cs_Julien39 3

Avec quelques mots c'est encore mieux Ajouter un commentaire

Codes Sources a aidé 101 internautes ce mois-ci

Commenter la réponse de cs_Julien39
Sphaxounet0 20 Messages postés mardi 30 mars 2010Date d'inscription 27 avril 2012 Dernière intervention - 27 avril 2012 à 11:36
1
Merci
Ah ! J'ai compris comment on utilisait les threads !

Ce que je veux c'est :

fonctionsA();
barreDeProgression();//Cette barre s'affiche pendant 4,5s et est INDEPENDANTE
//du reste du programme.
sleep(4500);
fonctionsB();


Le problème c'est que le sleep() endormait aussi la barreDeProgression() et donc elle s'affichait mal.

Ce qu'il fallait faire :

Thread t1{
   fonctionsA();
   barreDeProgression();
}.start();

Thread 2{
   t1.join();
   sleep(4500);
   fonctionsB();
}.start();


Pour que le sleep n'endorme pas tout ce qu'il se passe dans le thread 1.
Commenter la réponse de Sphaxounet0
sanfujinkai - 21 juin 2016 à 15:02
1
Merci
il y a plus simple , mettre un return a la premier fonction ( return n'import quoi ).


boolean fonctionQuiCrééUnFichier(){
....
....
return True;
};



ensuite la deuxieme dois attendre la fin de la premiere fonction car il y a un return (VARIABLE na pas d'utilité a part de faire attendre l'execution car il dois le remplir avec le return de la fonction);



try{
boolean VARIBLE =fonctionQuiCrééUnFichier();
fonctionQuiUtiliseLeFichier();

.....
Commenter la réponse de sanfujinkai
Sphaxounet0 20 Messages postés mardi 30 mars 2010Date d'inscription 27 avril 2012 Dernière intervention - 25 avril 2012 à 15:48
0
Merci
Oui mais comment je réalise la pause entre les threads ?

Et quand j'utilise des objets dans les Threads, j'ai une erreur "local variable var is accessed from within inner class; needs to be declared final".
   final Thread t1 = new Thread(){
      @Override
      public void run(){
         var = fonctionQuiCrééUnFichier();
      }
   };
Commenter la réponse de Sphaxounet0
cs_Julien39 6450 Messages postés mardi 8 mars 2005Date d'inscription 17 mai 2018 Dernière intervention - 26 avril 2012 à 09:30
0
Merci
Tu ne réalises pas de pause, la fonction .join() te permet d'attendre la fin du thread. C'est quoi var ? Ce n'était pas dans ton exemple au départ. Si tu le met en attribut de la classe, tu n'auras plus de soucis et plus besoin de la déclarer en final.
Commenter la réponse de cs_Julien39
Sphaxounet0 20 Messages postés mardi 30 mars 2010Date d'inscription 27 avril 2012 Dernière intervention - 26 avril 2012 à 10:37
0
Merci
En fait mon code de départ c'est :
public class MonOutil {
    public Donnees lancement() throws IOException, Exception {

        //DECLARATIONS
        File fichierSource;
        File fichierDestination =  new File("C:\\Windows\\Temp\\nouveau.pdf");
        Donnees donnees = new Donnees();
        Progression progress = new Progression();

        try {
            //Sélection du fichier
            donnees.fichier = choisirFichier();
            System.out.println("Le fichier choisi est : " + donnees.fichier);

            //Copie du fichier et renommage
            fichierSource = new File(donnees.fichier);
            copierFichier(fichierSource, fichierDestination);
            System.out.println("C'est copié.");

            //Extraction Métadata
            extraireMetaData(fichierDestination);
            
            //progress.lance_progres(45);//Dure 4,5s.
            Thread.sleep(4500);
            donnees = lireFichier(donnees);

        } catch (Exception e) {
            e.printStackTrace();
        }
        return donnees;
    }

    public static void copierFichier(File src, File dest) throws IOException {...}
    public static String choisirFichier() throws Exception {...}
    public static void extraireMetaData(File adresseFichier) {...}
    public static Donnees lireFichier(Donnees donnees) {...}
    }


Cette classe MonOutil me permet de récupérer des donnees, que j'envoie à mon main via : donnees = outil.lancement(); puis j'affiche les valeurs de donnees dans une JFrame.

Avec les modifications que tu m'as données, mon code devient :
    public Donnees lancement() throws IOException, Exception {

        //DECLARATIONS
        File fichierSource;
        File fichierDestination  = new File("C:\\Windows\\Temp\\nouveau.pdf");
        Donnees donnees = new Donnees();
        Progression progress = new Progression();

        final Thread t1 = new Thread() {
            //@Override

            public void run() {
                try {
                    //Sélection du fichier
                    donnees.fichier = choisirFichier();
                    System.out.println("Le fichier choisi est : " + donnees.fichier);

                    //Copie du fichier et renommage
                    fichierSource = new File(donnees.fichier);
                    copierFichier(fichierSource, fichierDestination);
                    System.out.println("C'est copié.");

                    //Extraction Métadata
                    extraireMetaData(fichierDestination);
                } catch (Exception e) {
                    e.printStackTrace();
                }
            }
        };
        t1.start();
        new Thread() {
            //@Override

            public void run() {
                try {
                    t1.join();
                    progress.lance_progres(45);//Dure 4,5s.
                    donnees = lireFichier(donnees);
                } catch (Exception e) {
                    e.printStackTrace();
                }
            }
        };
        return donnees;
    }


Sauf que je reçois les erreurs suivantes :
[i]"local variable donnees is accessed from within inner class; needs to be declared final"
"local variable progress is accessed from within inner class; needs to be declared final"
"local variable fichierSource is accessed from within inner class; needs to be declared final"
"local variable fichierDestination is accessed from within inner class; needs to be declared final"/i

Je ne suis vraiment pas à l'aise avec l'encapsulation j'ai l'impression...
Commenter la réponse de Sphaxounet0
cs_Julien39 6450 Messages postés mardi 8 mars 2005Date d'inscription 17 mai 2018 Dernière intervention - 26 avril 2012 à 10:54
0
Merci
Fait les déclarations des attributs :

public class Machin {
    //DECLARATIONS
    private File fichierSource;
    private File fichierDestination = new File("C:\\Windows\\Temp\\nouveau.pdf");
    private Donnees donnees = new Donnees();
    private Progression progress = new Progression();

   public Donnees lancement() throws IOException, Exception {

        final Thread t1 = new Thread() {
            //@Override

            public void run() {
                try {
                    //Sélection du fichier
                    donnees.fichier = choisirFichier();
                    System.out.println("Le fichier choisi est : " + donnees.fichier);

                    //Copie du fichier et renommage
                    fichierSource = new File(donnees.fichier);
                    copierFichier(fichierSource, fichierDestination);
                    System.out.println("C'est copié.");

                    //Extraction Métadata
                    extraireMetaData(fichierDestination);
                } catch (Exception e) {
                    e.printStackTrace();
                }
            }
        };
        t1.start();
        new Thread() {
            //@Override

            public void run() {
                try {
                    t1.join();
                    progress.lance_progres(45);//Dure 4,5s.
                    donnees = lireFichier(donnees);
                } catch (Exception e) {
                    e.printStackTrace();
                }
            }
        };
        return donnees;
    }

}
Commenter la réponse de cs_Julien39
Sphaxounet0 20 Messages postés mardi 30 mars 2010Date d'inscription 27 avril 2012 Dernière intervention - 26 avril 2012 à 11:57
0
Merci
J'ai fait comme tu m'as dit, mais le programme n'entre pas dans le 2e run(). t1.join() semble ne pas fonctionner.
Commenter la réponse de Sphaxounet0
cs_Julien39 6450 Messages postés mardi 8 mars 2005Date d'inscription 17 mai 2018 Dernière intervention - 26 avril 2012 à 14:24
0
Merci
C'est normal qu'il n'entre pas dans le deuxième run et que t1.join() ne fonctionne pas, j'ai oublié de lancer le thread t2 :

Thread t2 = new Thread() {
            //@Override

            public void run() {
                try {
                    t1.join();
                    progress.lance_progres(45);//Dure 4,5s.
                    donnees = lireFichier(donnees);
                } catch (Exception e) {
                    e.printStackTrace();
                }
            }
        };
t2.start();
Commenter la réponse de cs_Julien39
Sphaxounet0 20 Messages postés mardi 30 mars 2010Date d'inscription 27 avril 2012 Dernière intervention - 26 avril 2012 à 14:36
0
Merci
Ca ne fonctionne pas.
Le 2e thread se lance sans attendre que le 1er soit terminé.
Etant donné que ce que j'attends c'est que progress.lance-progres(45); soit terminé, ne peut-on pas mettre un flag/signal (comme cela se fait en C) pour indiquer au thread 2 qu'il peut se lancer ?

Parce qu'en fait j'ai l'impression que ce système de start()/join() ne permet pas de faire de pause, mais seulement de donner un ordre d'exécution aux threads.
Commenter la réponse de Sphaxounet0
cs_Julien39 6450 Messages postés mardi 8 mars 2005Date d'inscription 17 mai 2018 Dernière intervention - 26 avril 2012 à 15:03
0
Merci
Si tu lis la doc :

public final void join()
                throws InterruptedException

    Waits for this thread to die. 


Et j'ai testé chez moi dans un autre contexte et ca marche. Ce que tu peux faire c'est ca :

public class Machin {
    //DECLARATIONS
    private File fichierSource;
    private File fichierDestination = new File("C:\\Windows\\Temp\\nouveau.pdf");
    private Donnees donnees = new Donnees();
    private Progression progress = new Progression();

   public Donnees lancement() throws IOException, Exception {

        final Thread t1 = new Thread() {
            //@Override

            public void run() {
                try {
                    //Sélection du fichier
                    donnees.fichier = choisirFichier();
                    System.out.println("Le fichier choisi est : " + donnees.fichier);

                    //Copie du fichier et renommage
                    fichierSource = new File(donnees.fichier);
                    copierFichier(fichierSource, fichierDestination);
                    System.out.println("C'est copié.");

                    //Extraction Métadata
                    extraireMetaData(fichierDestination);
                    System.out.println("t1 termine");
                } catch (Exception e) {
                    e.printStackTrace();
                }
            }
        };
        t1.start();
        new Thread() {
            //@Override

            public void run() {
                try {
                    t1.join();
                    System.out.println("t2 commence");
                    progress.lance_progres(45);//Dure 4,5s.
                    donnees = lireFichier(donnees);
                } catch (Exception e) {
                    e.printStackTrace();
                }
            }
        };
        return donnees;
    }

}


Si tu as le message t1 commence avant t2 termine, il y a bien un souci...
Commenter la réponse de cs_Julien39
cs_Julien39 6450 Messages postés mardi 8 mars 2005Date d'inscription 17 mai 2018 Dernière intervention - 26 avril 2012 à 15:11
0
Merci
Je n'aime pas trop le catch(Exception e) qui nous empêche peut être de voir où est le problème...
Commenter la réponse de cs_Julien39
Sphaxounet0 20 Messages postés mardi 30 mars 2010Date d'inscription 27 avril 2012 Dernière intervention - 26 avril 2012 à 15:17
0
Merci
Oui l'ordre est bien respecté.
Mais ce qu'il faudrait que le programme fasse c'est : donnees = lireFichier(donnees); ne se lance qu'à partir du moment où progress.lance_progres() est terminé.

lance_progres() est explicité dans le fichier Progression.java. Cette fonction est constituée d'un sleep() contenu dans une boucle for de telle sorte que cela dure 4,5s.
Je pense donc que ce qu'il faudrait faire c'est
1°) déplacer la ligne progress.lance_progres(45);//Dure 4,5s. dans le run du thread t1.
2°) mettre t1.join() à la fin de la boucle for de la fonction lance_progres().

Mais est-ce possible de faire en sorte que le Thread t1 de class Machin soit reconnu dans la fonction progres.lance_progres() ?
Commenter la réponse de Sphaxounet0
cs_Julien39 6450 Messages postés mardi 8 mars 2005Date d'inscription 17 mai 2018 Dernière intervention - 27 avril 2012 à 08:13
0
Merci
new Thread(){
@Override
public void run(){
progress.lance_progres();
}
}.start();
donnees = lireFichier(donnees);
Commenter la réponse de cs_Julien39
cs_Julien39 6450 Messages postés mardi 8 mars 2005Date d'inscription 17 mai 2018 Dernière intervention - 27 avril 2012 à 08:16
0
Merci
Mais bon, ca commence à devenir un peu lourd je trouve.
Commenter la réponse de cs_Julien39
Sphaxounet0 20 Messages postés mardi 30 mars 2010Date d'inscription 27 avril 2012 Dernière intervention - 27 avril 2012 à 09:12
0
Merci
Le système de thread start()/join() ne fonctionne pas.
Cela semble ne servir qu'à donner un ordre de fonctionnement.
Mais il n'y a pas moyen pour ces threads de savoir si les fonctions qu'ils utilisent sont terminées ou pas.

Ce qu'il me faudrait c'est utiliser des sémaphores du coup je pense.

public class Machin{
   //déclarations

   public Donnees lancement(){
      //Sélection du fichier
      donnees.fichier = choisirFichier();
      System.out.println("Le fichier choisi est : " + donnees.fichier);

      //Copie du fichier et renommage
      fichierSource = new File(donnees.fichier);
      copierFichier(fichierSource, fichierDestination);
      System.out.println("C'est copié.");

      //Extraction Métadata
      extraireMetaData(fichierDestination);
      progress.lance_progres(45);//Dure 4,5s.

      while(conditionSEMAPHORE){
      //Attendre tant que conditionSEMAPHORE est nul
      }
      donnees = lireFichier(donnees);
      return donnees;
   }
}

public class Progression{
   //Déclarations

   public void lance_progres(int rapidite){
      progr.go(rapidite);
   }
   
   public void go(int rap){
      //blabla
      monThread = new Thread(new MonRunnable());
      monThread.start();
   }

   public class MonRunnable implements Runnable {
      public void run() {
         for{
         //Dure 4,5 secondes
         }
         conditionSEMAPHORE = true;//SEMAPHORE disant "c'est bon tu peux y aller"
      }
   }
}


Je pense que c'est plutôt de cela dont j'ai besoin. Comment les mettre en place ?
Commenter la réponse de Sphaxounet0
cs_Julien39 6450 Messages postés mardi 8 mars 2005Date d'inscription 17 mai 2018 Dernière intervention - 27 avril 2012 à 09:58
0
Merci
Non, les sémaphores sont encapsulées dans la méthode join.

et d'ailleurs, les sémaphores, je fonctionnent pas comme tu le décris.

Si tu appelles une méthode comme la lecture d'un fichier dans un thread, cette méthode va ouvrir un nouveau thread et donc, tu n'attendras pas qu'elle termine. C'est ta méthode de lecture de fichier qu'il faut travailler : pour cela, il faut que la méthode de lecture de fichier soit le run d'un thread.

Mais si tu veux bricoler le mécanisme que tu décris plus haut, c'est ton choix. Pour cela, tu peux créer un fichier .LOCK à un endroit donné sur ton disque et attendre que ce fichier ait disparu pour lancer ton traitement. Il faudra que la méthode de lecture du fichier gère la création et la destruction de ce fichier.
Commenter la réponse de cs_Julien39
Sphaxounet0 20 Messages postés mardi 30 mars 2010Date d'inscription 27 avril 2012 Dernière intervention - 27 avril 2012 à 10:10
0
Merci
Ce qui serait plus simple c'est d'utiliser la méthode que tu me disais plus tôt (avec les 2 threads, start() et join()) en mettant le join() à la fin du for{} de ma classe Progression.
Mais comment faire en sorte que le start() et le join() puissent "communiquer" l'un depuis la classe Machin et l'autre depuis la classe Progression ?
Commenter la réponse de Sphaxounet0
cs_Julien39 6450 Messages postés mardi 8 mars 2005Date d'inscription 17 mai 2018 Dernière intervention - 27 avril 2012 à 10:40
0
Merci
Ils n'ont pas besoin de communiquer.

Est ce que tu peux m'expliquer précisément ce que tu essayes de faire ?
Commenter la réponse de cs_Julien39

Vous n'êtes pas encore membre ?

inscrivez-vous, c'est gratuit et ça prend moins d'une minute !

Les membres obtiennent plus de réponses que les utilisateurs anonymes.

Le fait d'être membre vous permet d'avoir un suivi détaillé de vos demandes et codes sources.

Le fait d'être membre vous permet d'avoir des options supplémentaires.