2012-09-26 131 views
1

在我的Java代碼threadB創建NB *的ThreadA和等待,直到MyObj中價值將等於NBmyobj最初等於0,並且每個線程A增加它,當它變得等於nb最後一個線程A通知ThreadB。爪哇 - obj.notify()似乎並沒有工作

運行程序時,threadB不會被通知並且不會繼續運行。有人能告訴我這段代碼中的問題在哪裏?

public class Myclass { 
    static Long myobj = new Long(0); 
    static int nb = 1; 

    public static void main(String[] args) { 

     ThreadA[] threadA = new ThreadA[nb]; 
     ThreadB threadB = new ThreadB(threadA); 
    } 
} 

public class ThreadA extends Thread { 
    public ThreadA() { 
     this.start(); 
    } 

    public void run() { 
     // do lot of computation 
     Myclass.myobj = Myclass.myobj + 1; 
     if (Myclass.myobj.intValue() == Myclass.myobj.nb) { 
      synchronized (Myclass.myobj) { 
       Myclass.myobj.notify(); 
      } 
     } 
    } 
} 

public class ThreadB extends Thread { 
    ThreadA[] threadA; 

    public ThreadB(ThreadA[] threadA) { 
     this.threadA = threadA; 
     this.start(); 
    } 

    public void run() { 
     for (int i = 0; i < threadA.length; i++) { 
      threadA[i] = new ThreadA(); 
     } 

     synchronized (Myclass.myobj) { 
      while (Myclass.myobj.intValue() != Myclass.myobj.nb) { 
       Myclass.myobj.wait(); 
      } 
     } 
    } 
} 
+0

好的。當你創建ThreadB時,你給它一個具有certian大小的空數組,對嗎? – romedius

+0

是的。這是錯的嗎? – user1027336

回答

2

你在等待一個對象,並通知在不同的一個,因爲ThreadA中分配一個新的對象來Myclass.myobj並通知這個新對象。

使用專用的鎖對象,並確保每個對myObj的訪問都由此鎖對象保護。

或者更好的是,使用java.util.concurrent包中的更高級併發抽象。

+0

這就是我所懷疑的。我會嘗試與鎖對象..希望它不會那麼複雜。否則只有使用wait()和notify()才能正確執行它? – user1027336

+0

這是可能的,就像在彙編程序中編寫Web應用程序一樣。更高層次的抽象使生活更簡單和更安全。 –

9

我被所有可能是錯誤的東西所困惑,但沒有引起問題。

真正的問題是,

if (Myclass.myobj.intValue() == Myclass.myobj.nb) 

永遠不會每到這個被稱爲myobj < nb


我怎麼會寫這樣的代碼時爲真實?

int nb = .... 

ExecutorService es = Executors.newFixedThreadPool(nb) 
for (int i = 0; i < nb; i++) 
    es.submit(new Runnable() { 
     @Override 
     public void run() { 
      // do lot of computation 
     } 
    }); 
es.shutdown(); 
es.awaitTermination(1, TimeUnit.HOURS); 

有這麼多的事情,以改善這裏我覺得有必要列出它們

  • 不使用正確的格式。
  • 確實提供可能編譯的代碼
  • 不鎖定可變字段。這不會做你期望的,因爲你每次都會鎖定不同的對象。
  • 當您的意思是使用long時,請勿使用Long。在這個原因中,你似乎想要使用int
  • 不會創建new Long(0),因爲您可以使用更高效的自動裝箱。如果你這樣做,不要把它用作鎖定的對象。
  • 請勿在線程之間使用可變的static字段。
  • 不延伸Thread。創建一個傳遞給線程的Runnable。
  • 不要在構造函數中啓動線程。
  • 不使用數組將線程傳遞給另一個線程。尤其是在該線程開始之前它不會被設置。
  • 只讀取/檢查同步塊內的受保護值。
  • 我不會使用一個線程來創建另一個線程,這個線程被傳回原始線程。

但是,您的基本問題是您正在等待與您通知的對象不同的對象。

synchronized(Myclass.myobj){ // lock the object you might be waiting on. 
    Myclass.myobj=Myclass.myobj+1; // change this to another object. 
    Myclass.myobj.notify(); // notify a different object. 
} 
+0

+1爲重點。 –

+0

謝謝你的有趣回答......你提到的第一個問題是我在編輯我的問題時犯的一個錯誤(現在已經糾正了)。對於你提到的最後一個問題,我不明白爲什麼Myclass.myobj = Myclass.myobj + 1;將對象更改爲另一個,以及如何增加myobj的值而不更改它? – user1027336

+0

好吧,由於我提到的其他原因,它仍然無法工作。 ;) –