Сразу говорю, я новичок в написании многопоточных приложений, так что не судите строго:) У меня есть сервлет, в котором асинхронно производятся действия с базой данных. Ответ на http запрос будет готов только тогда, когда действия с базой данных будут произведены. В конце асинхронного метода onDataChange() вызывается метод responseReadyListener, который должен продолжить работу основного потока.
@Override
public void doPost(HttpServletRequest req, HttpServletResponse resp)
throws IOException {
//...
//вызывается при завершении работы с базой данных
responseReadyListener = new ResponseReadyListener() {
@Override
public void onResponseReady() {
responseReady[0] = true;
Log.info("onResponseReady");
synchronized (this) {
this.notify();
Log.info("threadNotified");
}
}
};
ref.addListenerForSingleValueEvent(new ValueEventListener() {
@Override
public void onDataChange(DataSnapshot dataSnapshot) {
//асинхронный метод. После завершения работы с базой данных
//вызывается onResponseReady(), который должен продолжить
//работу основного потока.
responseReadyListener.onResponseReady();
}
});
//основной поток, не должен завершаться пока responseReady[0] = false;
while (!responseReady[0]) {
Log.info("entered stopping loop");
try {
synchronized (this) {
if (!responseReady[0]) {
Log.info("stoppingPerformed");
this.wait();
}
}
} catch (InterruptedException e) {
e.printStackTrace();
}
}
Log.info("respSent");
}
}
Все логи, которые у меня выполняются:
INFO: entered stopping loop
INFO: stoppingPerformed
INFO: onResponseReady
INFO: threadNotified
Далее больше ничего не выполняется, как будто зависает. В чем может быть проблема? Никаких эксепшенов нет.
Подозреваю что проблема в синхронизации на разных объектах.
this
во вложенном классе относится ко вложенному классу, в данном случае к анонимной реализации ResponseReadyListener
:
//this здесь относится к анонимной реализации Listener
//а не к сервлету
//можете вывести this в лог для проверки.
synchronized (this) {
this.notify();
Log.info("threadNotified");
}
Исправить это можно обратившись к this
родительского класса:
synchronized (<Имя класса-сервлета>.this) {
<Имя класса-сервлета>.this.notify();
Log.info("threadNotified");
}
либо выбрать какой-нибудь другой объект для синхронизации.
З.Ы. Также я не уверен, что изменения в responseReady
будут доступны в родительском потоке. Я бы использовал вместо массива из одного элемента потокобезопасный класс, вроде AtomicBoolean
.
Айфон мало держит заряд, разбираемся с проблемой вместе с AppLab
Перевод документов на английский язык: Важность и ключевые аспекты
Не могу заменить русские буквы на английскиеНапример ,если я напишу я напишу "один" , программа должна вывести "odin"
Есть задание, где сначала надо вычислить слова с длинной слова больше среднего значения, a потом отсортировать их так, чтобы сначала шли слова...
Добрый день! Имеется старый проект QEMU for Android, который не обновлялся с 2010 года (то есть почти 8 лет)Соответственно, проект не имеет ни Runtime Permissions,...