0

J'essaie de synchroniser deux threads - le thread "Main" et un exécutable. J'obtiens le IllegalMonitorStateException, mais je ne comprends pas complètement ce que signifie "vous n'avez pas le verrou de l'objet".Synchronisation de threads en Java, IllegalMonitorStateException

Voici mon code:

public class ThreadsTest { 
    private static ThreadsTest instance; 
    public volatile boolean flag = false; 

    public void doStuff() { 
     System.out.println("first"); 

     this.flag = true; 

    } 

    public Runnable mDrawer = new Runnable() { 

     public void run() { 
      synchronized (ThreadsTest.getInstance()) { 
       while (flag == false) 
        try { 
         wait(); 
        } catch (InterruptedException ie) { 
         System.out.println("second"); 
        } 
      } 



     } 
    }; 

    public static ThreadsTest getInstance() { 
     if (ThreadsTest.instance == null) { 
      ThreadsTest.instance = new ThreadsTest(); 
     } 
     return ThreadsTest.instance; 
    } 

    private ThreadsTest() { 
    } 

    public static void main(String[] args) { 
     ThreadsTest t = ThreadsTest.getInstance(); 
     t.mDrawer.run(); 
     t.doStuff(); 

    } 
} 

Répondre

2

Vous pouvez appeler wait() méthode uniquement sur les objets que vous synchronisation sur. Donc, puisque vous avez synchronized (ThreadsTest.getInstance()), vous devez écrire ThreadsTest.getInstance().wait().

Je ne sais pas ce que vous essayez de tester ici exactement, si elle est juste échantillon de synchronisation de fil de base, alors vous devriez changer votre code pour

public class ThreadsTest { 
    private static ThreadsTest instance; 
    public volatile boolean flag = false; 

    public void doStuff() { 
     System.out.println("first"); 
     this.flag = true; 
     synchronized (getInstance()) { 
      getInstance().notifyAll(); 
     } 
    } 

    public Runnable mDrawer = new Runnable() { 

     public void run() { 
      synchronized (ThreadsTest.getInstance()) { 
       while (flag == false) 
        try { 
         ThreadsTest.getInstance().wait(); 
        } catch (InterruptedException ie) { 
         System.out.println("second"); 
        } 
      } 



     } 
    }; 

    public static ThreadsTest getInstance() { 
     if (ThreadsTest.instance == null) { 
      ThreadsTest.instance = new ThreadsTest(); 
     } 
     return ThreadsTest.instance; 
    } 

    private ThreadsTest() { 
    } 

    public static void main(String[] args) throws InterruptedException { 
     ThreadsTest t = ThreadsTest.getInstance(); 
     new Thread(t.mDrawer).start(); 
     Thread.sleep(1000L); // let other thread start, so it won't skip our notify() 
     t.doStuff(); 
    } 
} 
+0

bonne note en effet. J'ai changé le code, et j'appelle maintenant ThreadsTest.getInstance(). Wait(). Malheureusement, le résultat de ceci est que mon application "se fige". – George

+0

Erm :) Bien sûr, puisqu'il n'y a pas d'autre thread dans votre application pour envoyer votre 'wait()' signal de se réveiller. Je vais mettre à jour la réponse pour refléter cela –

+0

Merci, mon pote! Hallelujah! J'ai maintenant une bonne idée de quoi et pourquoi gèle – George