Почему этот метод вызывает исключение IllegalMonitorStateException? - PullRequest
2 голосов
/ 06 мая 2010
  public static synchronized void main(String[] args) throws InterruptedException {
    Thread t = new Thread();
    t.start();
    System.out.print("X");
    t.wait(10000);
    System.out.print("Y");
  }
  • В чем проблема с этим методом?
  • Как теперь избежать таких проблем?

Ответы [ 2 ]

2 голосов
/ 06 мая 2010

Есть несколько проблем с этим кодом. Я подозреваю, что вы пытаетесь написать что-то вроде этого:

public static synchronized void main(String[] args) throws InterruptedException {
  System.out.print("X");
  Thread.sleep(10000);
  System.out.print("Y");
}

Метод Thread.sleep() приостановит текущий поток на указанный интервал. Object.wait() это совсем другое, и вряд ли это то, что вы хотите.

Вы можете видеть, как я удалил ветку t. Если вы действительно хотите создать отдельный поток и получить распечатки, созданные в этом потоке, вам нужно дать этому потоку что-то делать. Самый простой способ сделать это - переопределить метод потока run() и получить там код потока:

public static synchronized void main(String[] args) {
  Thread t = new Thread() {
    public void run() {
      System.out.print("X");
      try { Thread.sleep(10000); } catch (InterruptedException e) { }
      System.out.print("Y");
    }
  };

  t.start();
}

Как написано, ваш исходный код фактически создавал поток без тела потока, поэтому, когда вы вызываете t.start(), пустой поток просто запускается в фоновом режиме и затем сразу же умирает.

Обратите внимание, что мне пришлось добавить предложение try / catch для InterruptedException теперь, когда вызов сна перенесен в поток. run() не разрешено генерировать исключения, поэтому теперь, к сожалению, мы должны перехватить и игнорировать исключение.

Другой способ написать это - выполнить часть работы в потоке t, а остальную часть работы - в основном потоке. Вот пример того, как вы можете разделить работу на два потока:

public static synchronized void main(String[] args) throws InterruptedException {
  Thread t = new Thread() {
    public void run() {
      System.out.print("X");
      try { Thread.sleep(10000); } catch (InterruptedException e) { }
    }
  };

  t.start();
  t.join();

  System.out.print("Y");
}

Когда это вызывает t.join(), он будет ждать завершения потока, что займет 10 секунд с момента его сна. После завершения потока метод join() вернется и позволит продолжить основной поток. Конечный результат будет выглядеть одинаково для пользователя: программа напечатает X, сделает паузу на 10 секунд, а затем напечатает Y.

1 голос
/ 06 мая 2010

Ну, предложения Джона сделают это.Но вы все равно можете почувствовать размытость относительно произошедшего исключения.Для этого я бы хотел, чтобы вы прочитали документацию по методу Object.wait () и IllegalMonitorStateException .

.Имейте в виду, что, черт возьми, монитор объекта.Так что здесь это из wikibooks ,

Каждый объект имеет «Монитор объектов».По сути, это «семафор», указывающий, выполняется ли поток кода критической секции потоком или нет.Прежде чем критический раздел может быть выполнен, Поток должен получить «Монитор объектов».Только один поток может одновременно владеть монитором этого объекта.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...