Я искал способ заставить один поток ждать / спать, пока другой поток не сигнализировал, что что-то было готово. Ожидающий поток должен проснуться, обработать данные, которые были сделаны доступными, а затем go вернуться в спящий режим, пока другой поток снова не подаст сигнал.
Самый простой метод, который я смог найти, был Object.wait()
и Object.notify()
, который ведет себя как семафор, инициализированный значением 0. Однако без операторов synchronized
около notify/wait
, Java всегда выдает IllegalMonitorStateException
, когда поток не является владельцем монитора. Поэтому я просто поместил их вокруг кода, как показано ниже.
THREAD 1: бесконечный запуск l oop
public class Main {
private Handler handler; // only one instance (singleton pattern)
public void listen() {
while (true) {
try {
synchronized (handler) {
handler.wait();
int value = handler.getSize();
// do something
}
} catch (InterruptedException e) {
// ...
}
}
}
}
THREAD 2: Некоторые другие вызовы класса removeItem
public class Handler {
// SINGLETON PATTERN - ONLY ONE INSTANCE
private ArrayList<Integer> sharedList;
private Handler() {
sharedList = new ArrayList<>();
}
public void addItem(Integer i) {
synchronized (sharedList) {
// add to list
}
}
public void removeItem(int i) {
synchronized (sharedList) {
// remove item
// notify that something is removed
synchronized (this) {
this.notify(); // this == handler
}
}
}
public int getSize() {
synchronized (sharedList) {
return sharedList.size();
}
}
}
Кажется, что он работает отлично, но не уверен, что есть скрытая ошибка. Мой вопрос: это безопасно? wait
снимает ли блокировку экземпляра для handler/this
, чтобы notify
могла получить блокировку?