2016-10-29 50 views
0

我試圖讓兩個線程相互打印出來的東西,但結果我得到的是:Java多線程錯誤`java.lang.IllegalMonitorStateException`

0 
Exception in thread "Thread-0" wait in decrement 
java.lang.IllegalMonitorStateException 
    at java.lang.Object.notify(Native Method) 
    at thread.Multithread2.increment(Multithread2.java:38) 
    at thread.Multithread2.run(Multithread2.java:18) 
    at java.lang.Thread.run(Unknown Source) 

我已經包含在synchronized塊共享對象和調用等待()/通知()這個對象。我不知道爲什麼它仍然會拋出異常。

public class Multithread2 implements Runnable { 

    private Integer integer; 
    private int method; 

    public Multithread2(Integer integer, int method) { 
     this.integer = integer; 
     this.method = method; 
    } 

    @Override 
    public void run() { 
     try { 
      Thread.sleep(20); 
      for(int i = 0; i < 5; i++) { 
       if(method == 1) { 
        increment(); 
       } else { 
        decrement(); 
       } 
      } 
     } catch (InterruptedException e) { 
      e.printStackTrace(); 
     } 
    } 

    public void increment() throws InterruptedException { 
     synchronized(integer) { 
      while(integer > 0) { 
       integer.wait(); 
      } 
      System.out.println(integer); 
      integer++; 
      integer.notify(); 
     } 
    } 

    public void decrement() throws InterruptedException { 
     synchronized(integer) { 
      while(integer <= 0) { 
       integer.wait(); 
      } 
      System.out.println("decrement: " + integer); 
      integer--; 
      integer.notify(); 
     } 
    } 
} 

主要方法:

Integer integer = new Integer(0); 
Thread t1 = new Thread(new Multithread2(integer, 1)); 
t1.start(); 
Thread t2 = new Thread(new Multithread2(integer, 2)); 
t2.start(); 
+1

'integer ++'與'integer = integer + 1'相同。你不是在'synchronized'同一個'integer'上調用'notify()'。 –

回答

2
integer++ 

相當於

integer = Integer.valueOf(integer.getValue() + 1); 

所以初始化與一個不同的整數實例的整數變量。整數是不可變的,所以它的狀態不能改變。既然你在這個新的Integer實例上調用了notify(),並且你沒有獲得這個新實例的鎖,你就會得到這個異常。

使用你自己的,可變的,線程安全的Counter類。在共享的,不可變的Integer實例上同步是一個糟糕的主意。順便說一句,一個好的經驗法則是使你同步的字段爲final。如果這樣做會導致編譯錯誤,並且在這種情況下編譯錯誤是您的朋友,前提是您注意實際上對您說的內容。

+0

或者我只是想'AtomicInteger'。 –

+0

是的,你也可以使用它。 –

+0

「這樣做會導致編譯錯誤。」 ......並且在這種情況下編譯錯誤是你的朋友,只要你注意實際上對你說的話。 –