2016-10-29 46 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

“这样做会导致编译错误。” ......并且在这种情况下编译错误是你的朋友,只要你注意实际上对你说的话。 –