2016-04-29 44 views
1

我有一個Runnable類A的內部函數工作:無法獲得notifyAll的像預期的那樣

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

我有一個Runnable 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); 
    } 
} 

當我運行該程序時,即使等待條件計算結果爲true,它也會在打印到函數3之前始終打印在函數1中。

在打印函數1中的值之前,我需要做什麼來打印函數3中的值?

回答

1

看起來好像你可能會多次運行function1來遞減函數2的值,然後在函數3中進行while循環檢查。因此,首先,在這種情況下,期望function1在function3之前打印是非常正常的,因爲function3在打印語句之前等待1秒,而在此期間,function1可以做任何想要的操作。

其次,或許更優雅的解決方案是在function1中檢查function2的值,然後在它爲== 0的情況下檢查notifyAll()。這樣,函數3中就不需要while循環,它只是使用wait()並等待來自function1的notifyAll()調用。

我的意思: 功能1加

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

功能3除去while循環

// no while loop 
lock.wait(); 

然後回答原來的問題,首先要保證內部功能3打印出如果功能1通話lock.wait聲明()在notifyAll()之後並在函數3的末尾添加notifyAll()。

下面的編譯類說明。

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

無論如何,由於虛假的喚醒,你不需要while循環嗎? –

+0

你是對的。當我寫我的答案時,我並沒有想到。你還需要一個while循環來封裝基於其他條件的function1 wait(),可能是由函數3設置的布爾值... – HunterCM