2015-12-23 2 views
3

Ниже программа должна печатать даже и нечетные числа двух разных потоков, но я получаю незаконное исключение для монитора уведомит метод в коде ниже:Получение незаконного состояния исключения монитора на извещать

public class oddeven { 
    static volatile Integer t = 0; 

    public static void main(String as[]) { 
     oddrunnable or = new oddrunnable(t); 
     evenrunnable er = new evenrunnable(t); 

     Thread t1 = new Thread(or, "odd"); 
     Thread t2 = new Thread(er, "even"); 

     t1.start(); 
     t2.start(); 

    } 

} 

class oddrunnable implements Runnable { 
    Integer t; 

    public oddrunnable(Integer t) { 
     this.t = t; 
    } 

    @Override 
    public void run() { 
     // TODO Auto-generated method stub 

     synchronized (t) { 
      while (true) { 

       if (t % 2 == 0) { 
        try { 
         t.wait(); 
        } catch (InterruptedException e) { 
         // TODO Auto-generated catch block 
         e.printStackTrace(); 
        } 
       } 
       System.out.println("Current thread id " + Thread.currentThread().getName()); 
       t++; 
       t.notify(); 
      } 
     } 
    } 

} 

class evenrunnable implements Runnable { 
    Integer t; 

    public evenrunnable(Integer t) { 
     this.t = t; 
    } 

    @Override 
    public void run() { 
     // TODO Auto-generated method stub 

     // TODO Auto-generated method stub 

     synchronized (t) { 
      while (true) { 

       if (t % 2 != 0) { 
        try { 
         t.wait(); 
        } catch (InterruptedException e) { 
         // TODO Auto-generated catch block 
         e.printStackTrace(); 
        } 
       } 
       System.out.println("Current thread id " + Thread.currentThread().getName()); 
       t++; 
       t.notify(); // <-------------------exception on this line 
      } 
     } 

    } 

} 

Уведомлять метод вызывается для самого синхронизированного объекта. Не знаю, почему это приходит:

Current thread id even 
Exception in thread "even" java.lang.IllegalMonitorStateException 
    at java.lang.Object.notify(Native Method) 
    at evenrunnable.run(oddeven.java:86) 
    at java.lang.Thread.run(Thread.java:619) 
+0

http://stackoverflow.com/questions/25733718/illegalmonitorstateexception-on-notify подобный вопрос. принятый ответ объясняет это хорошо. – WannaBeCoder

ответ

6

Целые в Java обертке неизменны, поэтому, как только вы t++, вы собираетесь назначить новый объект Integer, который вы не взяли замок против и, следовательно, вы получите IllegalMonitorStateException.

Вместо Integer используйте AtomicInteger, а затем используйте incrementAndGet api, чтобы увеличить значение счетчика.

+0

для объектов Integer t ++ эквивалентен для t = Integer.valueOf (t.intValue() + 1); – AdamSkywalker

1

Проблема заключается в использовании объекта Integer для синхронизации и выполнения операции инкремента (++). Я думаю, что его создание нового целочисленного объекта, а не вся синхронизированная логика, будет зависеть. Я не уверен в этом, так как при отладке кода eclipse не показывал, создал ли он новый объект.

Лучшей альтернативой является использование некоторого объекта-обертки вокруг вашего целого или класса AtomicInteger. Вот ваш код с классом AtomicInteger используется

public class oddeven { 
    static volatile AtomicInteger t = new AtomicInteger(0); 

    public static void main(String as[]) { 
     oddrunnable or = new oddrunnable(t); 
     evenrunnable er = new evenrunnable(t); 

     Thread t1 = new Thread(or, "odd"); 
     Thread t2 = new Thread(er, "even"); 

     t1.start(); 
     t2.start(); 

    } 

} 

class oddrunnable implements Runnable { 
    AtomicInteger t; 

    public oddrunnable(AtomicInteger t) { 
     this.t = t; 
    } 

    @Override 
    public void run() { 
     // TODO Auto-generated method stub 

     synchronized (t) { 
      while (true) { 

       if (t.intValue() % 2 == 0) { 
        try { 
         t.wait(); 
        } catch (InterruptedException e) { 
         // TODO Auto-generated catch block 
         e.printStackTrace(); 
        } 
       } 
       System.out.println("Current thread id " + Thread.currentThread().getName()); 
       t.incrementAndGet(); 
       t.notify(); 
      } 
     } 
    } 

} 

class evenrunnable implements Runnable { 
    AtomicInteger t; 

    public evenrunnable(AtomicInteger t) { 
     this.t = t; 
    } 

    @Override 
    public void run() { 
     // TODO Auto-generated method stub 

     // TODO Auto-generated method stub 

     synchronized (t) { 
      while (true) { 

       if (t.intValue() % 2 != 0) { 
        try { 
         t.wait(); 
        } catch (InterruptedException e) { 
         // TODO Auto-generated catch block 
         e.printStackTrace(); 
        } 
       } 
       System.out.println("Current thread id " + Thread.currentThread().getName()); 
       t.incrementAndGet(); 

       t.notify(); // <-------------------exception on this line 
      } 
     } 

    } 

} 
Смежные вопросы