2014-09-08 5 views
1

Я новичок в использовании wait() и notify() в Java, и я получаю исключение IllegalMonitorStateException.IllegalMonitorStateException on notify() при синхронизации по Integer

Главного Код

public class ThreadTest { 

    private static Integer state = 0; 
    public static void main(String[] args) { 

     synchronized(state) { 
      System.out.println("Starting thread"); 

      Thread t = new Thread(new AnotherTest()); 
      t.start(); 

      synchronized(state) { 
       state = 0; 
       while(state == 0) { 
        try { 
         state.wait(1000); 
        } catch (InterruptedException e) { 
         // TODO Auto-generated catch block 
         e.printStackTrace(); 
        } 
       } 
       System.out.println("State is: " + state); 
      } 
     } 
    } 

    public static class AnotherTest implements Runnable { 

     @Override 
     public void run() { 
      synchronized(state) { 
       state = 1; 
       state.notify(); 
      } 

     } 

    } 
} 

Я получаю IllegalMonitorStateException какого state.notify() называется. Есть идеи?

Редактировать: На основании нижеприведенного ответа приведен код, который работает. В качестве побочного примечания, я впервые попробовал это с перечислением, которое имеет ту же проблему с использованием Integer.

public class ThreadTest { 

    private static int state = 0; 
    private static Object monitor = new Object(); 
    public static void main(String[] args) { 

     synchronized(monitor) { 
      System.out.println("Starting thread"); 

      Thread t = new Thread(new AnotherTest()); 
      t.start(); 

      state = 0; 
      while(state == 0) { 
       try { 
        for(int i = 0; i < 5; i++) { 
         System.out.println("Waiting " + (5 - i) + " Seconds"); 
         Thread.sleep(1000); 
        } 
        monitor.wait(1000); 
       } catch (InterruptedException e) { 
        // TODO Auto-generated catch block 
        e.printStackTrace(); 
       } 
      } 
      System.out.println("State is: " + state); 
     } 
    } 

    public static class AnotherTest implements Runnable { 

     @Override 
     public void run() { 
      synchronized(monitor) { 
       state = 1; 
       monitor.notify(); 
      } 

     } 

    } 
} 

ответ

6

Это

private static Integer state = 0; 

эквивалентно

private static Integer state = Integer.valueOf(0); 

Заклятие valueOf(0) возвращает ссылку на объект Integer, назовем его А.

Затем вы делаете

synchronized(state) { 

ваш поток получает блокировку на объект, на который ссылается state, в настоящее время, что является А.

Затем сделать

state = 1; 

что эквивалентно

state = Integer.valueOf(1); 

, который дает вам другую ссылку на объект Integer, назовите его B и назначьте его state. Когда вы затем вызвать

state.notify(); 

вы вызываете notify() на объекте, B, для которых ваш поток не является владельцем монитора. Вы не можете позвонить notify или wait об объектах, для которых ваш поток не принадлежит к монитору.

+1

Это иллюстрирует, почему бессмысленно использовать 'wait/notify' на неизменяемых объектах, если ваш код зависит от изменения значения объекта ждали ... –

+0

Спасибо! Я знал, что мне не хватает чего-то довольно прямолинейного. – user3217229

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

  • Нет связанных вопросов^_^