Как бороться с Java-потоками - PullRequest
1 голос
/ 22 апреля 2009

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

Оба метода находятся в одном классе, но вызываются разными потоками.

public void processRefreshEvent(ManagerEvent event){
    //processing event
    //...
    //I'm done
    notify();
}


public synchronized void refresh() throws Exception {
    isRefreshing = true;    
    try {
                    manager.send(new refresh());
    } catch (ManagerException e) {
        isRefreshing = false;
    }

    try {
            wait(5000);
    } catch (InterruptedException e) {
    } finally{
        isRefreshing = false;
    }
}

при выполнении кода выше я получаю следующее исключение:

java.lang.IllegalMonitorStateException: current thread not owner
        at java.lang.Object.wait(Native Method)
        at Communicator.refresh(Communicator.java:203)
        ...

Как правильно «ждать» завершения другого потока. Спасибо.

Ответы [ 5 ]

2 голосов
/ 22 апреля 2009

Вам нужно синхронизировать ваши темы на мониторе. Например (используя текущий объект в качестве монитора):

public void processRefreshEvent(ManagerEvent event){
        //processing event
        //...
        //I'm done
    synchronized(this) {
        notify(); // you are basically notifying any thread who has blocked
                  // on this monitor - in our case, the instance of this object
    }
}


public synchronized void refresh() throws Exception {
        isRefreshing = true;    
        try {
                    manager.send(new refresh());
        } catch (ManagerException e) {
                isRefreshing = false;
        }

        try {
          synchronized(this) {
                wait(5000); // wait will give up the monitor
          }
        } catch (InterruptedException e) {
        } finally{
                isRefreshing = false;
        }
}
1 голос
/ 22 апреля 2009

Вы говорите, что хотите подождать, пока не закончится другой поток? Затем просто вызовите join () для объекта Thread, которого вы хотите ждать.

1 голос
/ 22 апреля 2009

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

Объявите "processRefreshEvent" synchronized или, что еще лучше, просто блок кода, который изменяет состояние, используемое методом refresh, вместе с вызовом notify().

public void processRefreshEvent(ManagerEvent event){
  // processing event
  synchronized (this) {
    // modify shared state with results of processing.
    notify();
  }
}
0 голосов
/ 22 апреля 2009

Пожалуйста, прочитайте JavaDoc на java.lang.Object.wait () и notify () .

Вы должны синхронизировать wait () с соответствующим монитором, в этом случае:

try{
    synchronized(this){
          wait(5000);
    }
}
catch (InterruptedException e) {
} finally{
            isRefreshing = false;
}
0 голосов
/ 22 апреля 2009

Из Object.wait() JavaDocs: «Текущий поток должен владеть монитором этого объекта». Поэтому вам нужно синхронизировать объект, который вы вызываете, с ожиданием.

В качестве альтернативы вы можете использовать BlockingQueue, который реализует Collection и Queue. BlockingQueue выполняет всю работу, ожидая и уведомляя. Ваш поток может просто позвонить take(), который будет блокироваться, пока не будут доступны данные. Вы добавляете данные в очередь, используя различные методы вставки (add, put и т. Д.). Кстати, методы вставки вызывают notify, в то время как take() вызывает wait.

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