У меня работает 2 темы.Один для сетевого события, другой для логики программы.Так как мне нужна некоторая синхронизация, я использую класс Java ReetrantLock.
Рабочий процесс сетевого потока:
- Получение сообщения
- Ожидание блокировки (myLock.lock ())
- Passсообщение логическому потоку
- снять блокировку (myLock.unlock ())
рабочий процесс логического потока:
- запустить некоторые системы
- дождаться блокировки (myLock.lock ())
- запустить 2 системы, которые обрабатывают сетевые сообщения внутри блока try catch (давайте назовем этот этап A )
- окончательно снять блокировку (myLock.unlock)
При такой конфигурации программа работает нормально в 95% случаев, но иногда она зависает, поэтому я запустил VisualVM, чтобы попытаться понять причину проблемы, и получил следующее
Как вы видите сетьпоток заблокирован, потому что он ожидает, пока логический поток не снимет блокировку повторного входа (что ожидается).Но по какой-то причине логическая нить застряла при печати стековой трассы?Я не могу понять, как я могу получить тупик из этой ситуации (застрял в фазе A ).
Я также пытался использовать JProfiler и получил те же результаты.Должен ли я верить тому, что вижу от этих профилировщиков (зависание стека)?
Кстати вот соответствующий код, где программа, кажется, зависает:
public void handle(EntityDeletionMessage message) {
try {
Entity toRemove = mapGameState.getEntityById(message.getEntityId());
mapGameState.removeEntity(toRemove);
} catch (EntityNotFoundException e) {
e.printStackTrace(); // From my understanding it freeze here
}
}
Кроме того, я не получаю трассировку стека на консоли, когда она зависает
Редактировать : Вот код из двух систем, которые должны быть синхронизированы с сетевым потоком (очевидно, они обе имеют одинаковую блокировку):
Система 1:
public void update(float deltaTime) {
lock.lock(); // It will be unlocked in the second system.
// process some network messages.
}
Система 2:
public void update(float deltaTime) {
while (networkMessages.size > 0) {
NetworkMessage message = networkMessages.removeFirst();
MessageHandler handler = messageHandlerManager.getHandler(message.getClass());
if (handler == null) {
Gdx.app.error("NetworkMessagesManagerSystem", "No handler for the message: " + message.getClass());
continue;
}
try {
handler.handle(message);
} catch (Exception e) {
e.printStackTrace();
}
}
lock.unlock(); // It was locked in the system 1
}