IllegalMonitorStateException на ожидании () вызов

До хранения Вашего DB "в синхронизации", когда другие редактируют его. Один путь вокруг этого состоит в том, чтобы получить Вашу схему DB при управлении версиями. Это не столь просто как подвергание Вашего исходного кода при управлении версиями, и существуют различные способы обработать его.

читает это сообщение при Кодировании Ужаса:

https://blog.codinghorror.com/get-your-database-under-version-control /

Не так само сообщение, но эти шесть статей он связывается с K. Scott Allen.

В основном то, что описано в тех статьях, является методом определения исходного состояния, схема базы данных, регистрируясь в .sql файле той базовой линии, и оттуда на в Вас пишет возрастающим .sql "сценариям изменения" каждый раз, когда Вы изменяете схему. Теперь каждый раз разработчик проверяет или обновляет рабочую копию, любые выдающиеся сценарии изменения будут выполнены. Необходимо будет настроить некоторые сценарии/инструменты, чтобы сделать это сами, если Вы не будете использовать платформу, которая делает это для Вас.

156
задан Joachim Sauer 8 October 2009 в 11:31
поделиться

5 ответов

Чтобы Object.wait () работал, вы должны быть в синхронизированном блоке.

Также я рекомендую посмотреть на пакеты параллелизма вместо старых пакетов многопоточности. Они более безопасны и проще работать с .

Удачного кодирования.

РЕДАКТИРОВАТЬ

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

167
ответ дан 23 November 2019 в 21:51
поделиться

wait определен в объекте , а не в потоке . Монитор в Thread немного непредсказуем.

Хотя все объекты Java имеют мониторы, обычно лучше иметь выделенную блокировку:

private final Object lock = new Object();

Вы можете немного упростить чтение диагностических данных за небольшую стоимость памяти (около 2 КБ на процесс) при использовании именованного класса:

private static final class Lock { }
private final Object lock = new Lock();

Чтобы wait или уведомить / notifyAll объект, вам необходимо удерживание блокировки с помощью оператора synchronized . Кроме того, вам понадобится цикл while , чтобы проверить условие пробуждения (найдите хороший текст по потоковой передаче, чтобы объяснить, почему).

synchronized (lock) {
    while (!isWakeupNeeded()) {
        lock.wait();
    }
}

Чтобы уведомить:

synchronized (lock) {
    makeWakeupNeeded();
    lock.notifyAll();
}

Хорошо бы понять как Java язык и java.util.concurrent. locks блокирует (и java.util.concurrent.atomic ) при переходе в многопоточность. Но всегда используйте структуры данных java.util.concurrent .

52
ответ дан 23 November 2019 в 21:51
поделиться

Судя по вашим комментариям, похоже, что вы делаете что-то вроде этого:

Thread thread = new Thread(new Runnable(){
    public void run() { // do stuff }});

thread.start();
...
thread.wait();

Есть три проблемы.

  1. Как говорили другие, obj.wait () может быть вызван только в том случае, если текущий поток содержит примитивную блокировку / мьютекс для obj . Если текущий поток не удерживает блокировку, вы получаете исключение, которое вы видите.

  2. Вызов thread.wait () не делает то, что вы, кажется, ожидаете. В частности, thread.wait () не заставляет назначенный поток ждать. Скорее он заставляет текущий поток ждать, пока какой-либо другой поток не вызовет thread.notify () или thread.notifyAll () .

    Фактически нет безопасный способ принудительно приостановить экземпляр Thread , если он этого не хочет. (Ближайший к этому способ Java - устаревший метод Thread.suspend () , но этот метод по своей сути небезопасен, как объясняется в документации Javadoc.)

    Если вы хотите запустить новый ] Поток для приостановки, лучший способ сделать это - создать экземпляр CountdownLatch и заставить вызов потока await () в защелке приостановить себя. Затем основной поток вызовет countDown () в защелке, чтобы позволить приостановленному потоку продолжить работу.

  3. Ортогонально предыдущим точкам, используя объект Thread в качестве блокировки / мьютекса. вызвать проблемы. Например, в javadoc для Thread :: join говорится:

    В этой реализации используется цикл вызовов this.wait , обусловленных this.isAlive . Поскольку поток завершает this. вызывается метод notifyAll . Рекомендуется, чтобы приложения не использовали wait , notify или notifyAll в экземплярах Thread .

5
ответ дан 23 November 2019 в 21:51
поделиться

Поскольку вы не опубликовали код, мы работаем в темноте. Каковы подробности исключения?

Вы вызываете Thread.wait () из потока, или вне его?

Я спрашиваю об этом, потому что, согласно javadoc для IllegalMonitorStateException, это:

Брошено, чтобы указать, что поток попытался ждать на мониторе объекта или уведомить другие потоки, ожидающие на мониторе объекта, не владея указанным монитором.

Чтобы прояснить этот ответ, этот вызов ожидания потока также вызывает исключение IllegalMonitorStateException, несмотря на то, что он вызывается из синхронизированного блока:


     private static final class Lock { }
     private final Object lock = new Lock();

    @Test
    public void testRun() {
        ThreadWorker worker = new ThreadWorker();
        System.out.println ("Starting worker");
        worker.start();
        System.out.println ("Worker started - telling it to wait");
        try {
            synchronized (lock) {
                worker.wait();
            }
        } catch (InterruptedException e1) {
            String msg = "InterruptedException: [" + e1.getLocalizedMessage() + "]";
            System.out.println (msg);
            e1.printStackTrace();
            System.out.flush();
        }
        System.out.println ("Worker done waiting, we're now waiting for it by joining");
        try {
            worker.join();
        } catch (InterruptedException ex) { }

    }
1
ответ дан 23 November 2019 в 21:51
поделиться

Вызов Thread.wait () имеет смысл внутри кода, который синхронизируется с объектом Thread.class. Я не думаю, что вы имели в виду.
Вы спрашиваете

Как я могу заставить поток ждать, пока он не получит уведомление?

Вы можете заставить ждать только ваш текущий поток. Любой другой поток можно только осторожно попросить подождать, если он согласен.
Если вы хотите дождаться какого-то условия, вам нужен объект блокировки - объект Thread.class - очень плохой выбор - это одноэлементный AFAIK, поэтому синхронизация с ним (за исключением статических методов Thread) опасна.
Детали синхронизации и ожидания уже объяснил Том Хотин. java.lang.IllegalMonitorStateException означает, что вы пытаетесь дождаться объекта, с которым вы не синхронизированы - это незаконно.

0
ответ дан 23 November 2019 в 21:51
поделиться
Другие вопросы по тегам:

Похожие вопросы: