2016-04-29 17 views
1
beabsichtigt zu arbeiten

Ich habe eine Funktion innerhalb einer Runnable Klasse A:Kann nicht bekommen notifyAll als

public void function1(){ 
    synchronized(lock){ 
     function2.decrease(); 
     lock.notifyAll(); 
     System.out.print(function2.getValue()); 
} 

Ich habe eine andere Funktion innerhalb eines Runnable Klasse B:

public void function3(){ 
    try{ 
     synchronized(lock){ 
      while(!(function2.getValue() != 0)){ 
       lock.wait(); 
      } 
      Thread.sleep(1000); 
      System.out.println(function2.getValue() + 10); 
     } 
    }catch(InterruptedException e){ 
     System.err.println(e); 
    } 
} 

Als ich führe das Programm aus, das immer in Funktion1 gedruckt wird, bevor es in Funktion3 druckt, selbst wenn die Wartebedingung wahr ist.

Was muss ich tun, um den Wert in Funktion3 zu drucken, bevor der Wert in Funktion1 gedruckt wird?

Antwort

1

Sieht so aus, als ob Sie wahrscheinlich function1 mehrmals ausführen, um den Wert von function2 zu dekrementieren, und dann while loop check in function3. Zunächst einmal ist es normal zu erwarten, dass Funktion1 in diesem Szenario vor Funktion3 druckt, da Funktion3 eine Sekunde vor der Druckanweisung wartet, während Funktion1 in der Zwischenzeit tun kann, was sie will. Ein eleganterer Lösungsansatz besteht darin, die Funktion von function2 in function1 zu überprüfen und notifyAll(), falls es == 0 ist. Auf diese Weise ist in function3 keine while-Schleife erforderlich und wird lediglich verwendet wait() und wartet auf einen notifyAll() - Aufruf von function1.

Was ich meine: Function1 hinzufügen

if(function2.getValue() == 0) 
    lock.notifyAll(); 

Funktion3 while-Schleife entfernen

// no while loop 
lock.wait(); 

Dann ursprüngliche Frage zu beantworten, function3 druckt zunächst innerhalb der if-Anweisung in function1 Aufruf lock.wait, um sicherzustellen,() nach notifyAll() und notiereAll() am Ende von function3.

Compilable-Klasse, die unten demonstriert.

public class StackSyncProb{ 
    private volatile int function2; 
    private Object lock = new Object(); 

    public static void main(String[] args){ 
     StackSyncProb s = new StackSyncProb(3); // function2 starts at 3 
     // start function3, which waits 
     s.runFunction3(); 
     // decrement using function1 until hit 0 (in this case, 3 times) 
     for(int i = 0; i < 3; i++){ 
      s.runFunction1(); 
     } 
    } 

    public StackSyncProb(int v){ 
     function2 = v; 
    } 

    public void runFunction1(){ 
     new Thread(new Run1()).start(); 
    } 

    public void runFunction3(){ 
     new Thread(new Run2()).start(); 
    } 

    public class Run1 implements Runnable{ 
     @Override 
     public void run(){ 
      function1(); 
     } 
     public void function1(){ 
      try{ 
      synchronized(lock){ 
       function2--; 
       // Use if statement to check inside function1 instead of in function3 
       if(function2 == 0){ 
        lock.notifyAll(); 
        // After notifying, wait until function3 done 
        lock.wait(); 
       } 
       System.out.println("function1: " + function2); 
      } 
      }catch(InterruptedException e){} 
     } 
    } 

    public class Run2 implements Runnable{ 
     @Override 
     public void run(){ 
      function3(); 
     } 
     public void function3(){ 
      try{ 
       synchronized(lock){ 
        // No while loop 
        lock.wait(); 
        Thread.sleep(1000); 
        System.out.println("function3: " + (function2 + 10)); 
        // Notify function1 it can complete and print 
        lock.notifyAll(); 
       } 
      }catch(InterruptedException e){ 
       System.err.println(e); 
      } 
     } 
    } 
} 
+0

Brauchen Sie die while-Schleife sowieso nicht, wegen eines unerwünschten Weckrufs? –

+0

Sie haben Recht. Ging mir nicht in den Sinn, als ich meine Antwort schrieb. Sie würden auch eine while-Schleife benötigen, die function1 wait() basierend auf einer anderen Bedingung umschließt, möglicherweise eine boolesche Funktion von function3 ... – HunterCM