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

Java Discussion :

Attente bloquante : comment faire?


Sujet :

Java

  1. #1
    Membre expert
    Avatar de ®om
    Profil pro
    Inscrit en
    Janvier 2005
    Messages
    2 815
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Janvier 2005
    Messages : 2 815
    Points : 3 080
    Points
    3 080
    Par défaut Attente bloquante : comment faire?
    Salut,

    Je souhaiterais faire une attente bloquante, notamment dans ce cas:
    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
    private void showXXX() {
        try {
            SwingUtilities.invokeAndWait(new Runnable() {
                public void run() {
                    MyJFrame frame = new MyJFrame();
                    frame.addWindowListener(new WindowAdapter() {
                        @Override public void windowClosed(WindowEvent e) {
                            arreteLAttenteBloquante();
                        }
                    }
                }
            }
        } catch(InvocationTargetException ite) {} catch(InterruptedException ie) {}
        attenteBloquante();
    }
    Comment coder les méthodes en gras (spécifiquement pour ce cas là)?

    En gros c'est pour ensuite faire:
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    showSplashScreenBloquant();
    actionsApresLeSplashOuSiLeChargementDuSplashAPlante();

  2. #2
    Membre confirmé
    Profil pro
    Inscrit en
    Juillet 2006
    Messages
    548
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Juillet 2006
    Messages : 548
    Points : 635
    Points
    635
    Par défaut
    Fais une recherche sur "SwingWorker", ça devrait te donner des idées

  3. #3
    Membre expert
    Avatar de ®om
    Profil pro
    Inscrit en
    Janvier 2005
    Messages
    2 815
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Janvier 2005
    Messages : 2 815
    Points : 3 080
    Points
    3 080
    Par défaut
    Citation Envoyé par the-gtm
    Fais une recherche sur "SwingWorker", ça devrait te donner des idées
    SwingWorker, ça serait à la place de mon invokeAndWait(...).
    Là c'est un autre problème, qui n'a pas de rapport avec l'EDT d'ailleurs...

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

    Tu peux utiliser les Semaphore de Java 5.0 :
    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
            System.out.println("DEBUT");
     
            final Semaphore semaphore = new Semaphore(1);
            semaphore.acquire(); // on demande le sémaphore
     
            // On affiche la JFrame dans l'EDT
            SwingUtilities.invokeLater(new Runnable() {
                public void run() {
                    MyJFrame frame = new MyJFrame();
                    frame.addWindowListener(new WindowAdapter() {
                        @Override public void windowClosed(WindowEvent e) {
                            semaphore.release(); // on libère la semaphore
                        }
                    });
                }
            });
     
     
            semaphore.acquire(); // on redemande la sémaphore
            // (bloquant car on ne peut en posséder qu'une instance)
     
            System.out.println(" FIN ");
    Sinon tu peux tout simplement utiliser le mécanisme de synchronisation de base : les wait()/notify() !
    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
            System.out.println("DEBUT");
     
            final Object lock = new Object();
     
            synchronized(lock) {
     
                // On affiche la JFrame dans l'EDT
                SwingUtilities.invokeLater(new Runnable() {
                    public void run() {
                        MyJFrame frame = new MyJFrame();
                        frame.addWindowListener(new WindowAdapter() {
                            @Override public void windowClosed(WindowEvent e) {
                                synchronized(lock) {
                                    lock.notify(); // on reveille le thread
                                }
                            }
                        });
                    }
                });
     
     
                lock.wait(); // on endors le thread courant
                // en attendant un appel à notify() depuis un autre thread
            }
     
            System.out.println(" FIN ");
    A noter que dans ces deux cas invokeAndWait() peut tout à fait être ramplacé invokeLater() car on n'a pas besoin d'attendre la fin du traitement (ici la fin du traitement survient lorsque le JFrame est affiché).

    a++

  5. #5
    Membre expert
    Avatar de ®om
    Profil pro
    Inscrit en
    Janvier 2005
    Messages
    2 815
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Janvier 2005
    Messages : 2 815
    Points : 3 080
    Points
    3 080
    Par défaut
    Nickel, les sémaphores je connaissais en C, je ne savais pas que ça existait (surtout si simplement, par rapport à C) en java...

    Sinon pour le wait()/notify(), je n'ai pas essayé, mais vu que tout le bloc est en synchronized(lock), il ne va jamais pouvoir lancer lock.notify(), car il est dans un autre bloc synchronized(lock), si?

  6. #6
    Membre expert
    Avatar de ®om
    Profil pro
    Inscrit en
    Janvier 2005
    Messages
    2 815
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Janvier 2005
    Messages : 2 815
    Points : 3 080
    Points
    3 080
    Par défaut
    Je rencontre maintenant un nouveau problème:
    Mon splashscreen se lance, le chargement se fait, c'est nickel... Puis mon splashscreen se dispose, et la fenêtre principale se lance... Sauf qu'elle se lance en "minimisé" (dans la barre en bas)...
    Un toFront() ou setExtendedState(NORMAL) n'y changent rien

    Du code pour aider:
    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
        private static void launchSplashScreenAndLoad() {
            final Semaphore semaphore = new Semaphore(1);
     
            try {
                final LoadingSplashScreen splash = LoadingSplashScreen.showSplashScreen(1500);
                // splashOk[0] = true;
                ModuleLoader.getModuleLoader().addLoadingListener(splash);
                /* On demande le sémaphore. */
                semaphore.acquire();
                /* On écoute la fermeture du splashscreen. */
                splash.addWindowListener(new WindowAdapter() {
     
                    @Override public void windowClosed(WindowEvent e) {
                        /* Sinon, pour une raison inconnue, l'évènement est déclenché 2x. */
                        splash.removeWindowListener(this);
                        /* On libère le sémaphore. */
                        semaphore.release();
                    }
                });
            } catch(SplashScreenException e) {
                Logger.getLogger("MyFreeTV").warning("Le splashscreen n'est pas disponible.");
            } catch(InterruptedException e) {
                Logger.getLogger("MyFreeTV").warning("Chargement du splashscreen interrompu.");
            }
     
            /* Charge les modules, et signale les chargements en cours au splashscreen. */
            ModuleLoader.getModuleLoader().load();
     
            try {
                /* On redemande le sémaphore (bloquant). */
                semaphore.acquire();
            } catch(InterruptedException e) {
                Logger.getLogger("MyFreeTV").warning("Chargement du splashscreen interrompu.");
            }
        }
     
        private static void initialize() {
            launchSplashScreenAndLoad();
     
            mainFrame = new MainFrame(); //donc pas dans l'EDT
        }
    Dans MainFrame:
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
        public MainFrame() {
            super("Titre de la fenêtre");
            ... //Construction de la fenêtre
            SwingUtilities.invokeLater(new Runnable() {
                public void run() {
                    setVisible(true);
                }
            }
        }
    Je lance l'appli en appelant initialize()...

  7. #7
    Membre confirmé
    Profil pro
    Inscrit en
    Juillet 2006
    Messages
    548
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Juillet 2006
    Messages : 548
    Points : 635
    Points
    635
    Par défaut
    tu as essayé pack() sur la frame ?

  8. #8
    Membre expert
    Avatar de ®om
    Profil pro
    Inscrit en
    Janvier 2005
    Messages
    2 815
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Janvier 2005
    Messages : 2 815
    Points : 3 080
    Points
    3 080
    Par défaut
    Citation Envoyé par the-gtm
    tu as essayé pack() sur la frame ?
    Non, mais c'est pas qu'elle est petite, elle apparait simplement uniquement ds la barre des tâches, si je clique sur la barre des tâches elle est à la bonne taille...

  9. #9
    Membre expert
    Avatar de ®om
    Profil pro
    Inscrit en
    Janvier 2005
    Messages
    2 815
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Janvier 2005
    Messages : 2 815
    Points : 3 080
    Points
    3 080
    Par défaut
    En fait ça marche... Sauf si je lance l'appli à partir de eclipse
    En .jar direct ça marche

  10. #10
    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 ®om
    Sinon pour le wait()/notify(), je n'ai pas essayé, mais vu que tout le bloc est en synchronized(lock), il ne va jamais pouvoir lancer lock.notify(), car il est dans un autre bloc synchronized(lock), si?
    Si si ca marche

    Les méthode wait() et notify() DOIVENT être appellé dans un bloc synchronized() sur l'instance de l'objet sur lequel elle sont appellé.
    En fait le wait() "libère" le lock pendant son sommeil, et on ne sors réellement du wait() qu'après qu'il ait récupéré le lock...


    a++

  11. #11
    Membre expert
    Avatar de ®om
    Profil pro
    Inscrit en
    Janvier 2005
    Messages
    2 815
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Janvier 2005
    Messages : 2 815
    Points : 3 080
    Points
    3 080
    Par défaut
    Citation Envoyé par ®om
    En fait ça marche... Sauf si je lance l'appli à partir de eclipse
    En .jar direct ça marche
    Euh, même en .jar direct, en fait ça se lance derrière le navigateur

    Qqn a une idée d'où ça peut venir?

  12. #12
    Membre expert
    Avatar de ®om
    Profil pro
    Inscrit en
    Janvier 2005
    Messages
    2 815
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Janvier 2005
    Messages : 2 815
    Points : 3 080
    Points
    3 080
    Par défaut
    Citation Envoyé par ®om
    Euh, même en .jar direct, en fait ça se lance derrière le navigateur

    Qqn a une idée d'où ça peut venir?
    Ca venait du fait que le splashscreen était en alwaysontop...
    Mais je ne vois pas pourquoi...

    D'ailleurs, même si je fais un setAlwaysOnTop(false) juste avant le dispose(), ça ne résoud pas le problème, je suis donc obligé d'enlever setAlwaysOnTop(true) au lancement du splash

  13. #13
    Membre expert
    Avatar de ®om
    Profil pro
    Inscrit en
    Janvier 2005
    Messages
    2 815
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Janvier 2005
    Messages : 2 815
    Points : 3 080
    Points
    3 080
    Par défaut
    adiGuba, concernant ta solution avec le wait()/notify(), il y a un problème...

    Si le notify() est effectué avant le wait() (ce qui est peu probable, mais possible), il y a un deadlock...

  14. #14
    Membre éclairé Avatar de Pollux
    Profil pro
    Inscrit en
    Avril 2005
    Messages
    706
    Détails du profil
    Informations personnelles :
    Âge : 38
    Localisation : Suisse

    Informations forums :
    Inscription : Avril 2005
    Messages : 706
    Points : 680
    Points
    680
    Par défaut
    Citation Envoyé par ®om
    Si le notify() est effectué avant le wait() (ce qui est peu probable, mais possible), il y a un deadlock...
    Mais pourquoi est-ce que tu ferais un notify avant un wait??

  15. #15
    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 Pollux
    Mais pourquoi est-ce que tu ferais un notify avant un wait??
    En général on utilise cela lorsqu'on fait deux tâches en parallèles : on effectue une tâche dans un thread secondaire et une autre dans le thread courant, puis on passe à la suite une fois que les deux tâches sont terminées (cela peut permettre par exemple de "partager" les résultats des deux tâches).

    Citation Envoyé par ®om
    Si le notify() est effectué avant le wait() (ce qui est peu probable, mais possible), il y a un deadlock...
    C'est en effet très probable si on ne peut pas être sûr du temps d'exécutions des deux tâches. La meilleure solution est d'utiliser le "double-check" en utilisant une valeur booléenne qui déterminera si la méthode notify a déjà été appellée. Par exemple :

    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 Main {
     
        private boolean notified = false;
     
        public void waitThis() {
            synchronized(this) {
                while (!this.notified) {
                    try {
                        this.wait();
                    } catch (InterruptedException e) {
                        e.printStackTrace();
                    }
                }
                this.notified = false;
            }
        }
     
        public void notifyThis() {
            synchronized(this) {
                this.notified = true;
                this.notify();
            }
        }
     
        /* Effectue une attente pour simuler un traitement */
        public static void sleeping(int ms) {
            try {
                Thread.sleep(ms);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }
     
        public static void main(String[] args) throws Exception {
     
            final Main m = new Main();
            new Thread() {
                public void run() {
     
                    sleeping(300);
     
                    System.out.println("notifyThis");
                    m.notifyThis();
                }
            }.start();
     
            sleeping(1000);
     
            System.out.println("waitThis");
            m.waitThis();
            System.out.println("END");
        }
    }
    Malgré le fait que le notify() soit appellé bien avant le wait(), on n'a pas de deadlock


    a++

    PS : toutefois le package concurrent de Java 5.0 permet de se passer de cela grâce à ses classes qui le gère déjà comme les BlockingQueue ou les Semaphore !

Discussions similaires

  1. [XL-2007] Comment faire un message d'attente durant la mise à jour de ma macro ?
    Par Debutant10 dans le forum Macros et VBA Excel
    Réponses: 5
    Dernier message: 10/05/2012, 21h34
  2. Réponses: 2
    Dernier message: 28/04/2009, 15h26
  3. Comment faire 2sec d'attente
    Par Bouboukick dans le forum Débuter avec Java
    Réponses: 6
    Dernier message: 03/06/2008, 02h48
  4. [VB.NET] comment faire un message d'attente
    Par hellosct1 dans le forum Windows Forms
    Réponses: 1
    Dernier message: 27/09/2006, 17h43

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