В моей java-программе для MUDRPG на данный момент два потока (если не ошибаюсь, движок писал не я). Один поток является чисто графическим и отображает все объекты Gui
, а другой поток обрабатывает все вычисления. Этот второй поток отвечает за сражения. В своем боевом коде я проверяю, существует ли графический интерфейс hitsplat, однако после нескольких успешных вызовов функции (каждый раз с другим номером) я застреваю с ошибкой ConcurrentModificationException
. Похоже, это потому, что в то время, когда эта битва пытается проверить, существуют ли хитсплаты, графический поток пытается отобразить вещи из LinkedHashMap
. Может кто-нибудь, пожалуйста, проинструктируйте меня, как правильно читать из LinkedHashMap
, чтобы избежать этой проблемы, или мне нужно вместо этого использовать ConcurrentHashMap
? Насколько я понимаю, LinkedHashMap
используется, потому что он может обрабатывать порядок, я не совсем уверен, верно ли то же самое для ConcurrentHashMap
.
Код, который обращается к LinkedHashMap в потоке вычислений:
private boolean checkHitsplats(){
System.out.println("I get called)");
while (true) {
try {
if (OneQuest.getInstance().getTickThread().getGuis()
.get("HitsplatPlayer") == null
&& OneQuest.getInstance().getTickThread().getGuis()
.get("HitsplatMonster1") == null
&& OneQuest.getInstance().getTickThread().getGuis()
.get("HitsplatMonster2") == null
&& OneQuest.getInstance().getTickThread().getGuis()
.get("HitsplatMonster3") == null) {
return false; // return false if none exist
} else
return true; // return true of any hitsplats exist
} catch (ConcurrentModificationException e) {
System.out.println("modification error");
}
}
}
Фрагмент кода, который циклически проходит через linkedHashMap для отображения графических элементов, где guis
— это LinkedHashMap со всеми добавленными графическими объектами.
private void tick() {
synchronized (guis) {
Iterator<Gui> iter = guis.values().iterator();
while (iter.hasNext()) {
Gui gui = iter.next();
if (gui.isShowing()) {
gui.render(window);
}
}
}
if (guiConsole.isShowing()) {
guiConsole.render(window);
}
}
Изменить: Версия 2 checkHitsplats, предложенная добрым человеком.
private boolean checkHitsplats(){
Object[] guis = OneQuest.getInstance().getTickThread().getGuis().values().toArray();
System.out.println("I get called)");
while (true) {
try {
for (int i = 0; i < guis.length; i++) {
if (((Gui) guis[i]).getGuiName() == "HitsplatPlayer"
|| ((Gui) guis[i]).getGuiName() == "HitsplatMonster1"
|| ((Gui) guis[i]).getGuiName() == "HitsplatMonster2"
|| ((Gui) guis[i]).getGuiName() == "HitsplatMonster3")
return true;
}
return false;
} catch (Exception e) {
}
}
==
! Вы не должны этого делать (даже если это может сработать в вашем конкретном случае, это опасная привычка). - person Joachim Sauer   schedule 10.06.2013checkHitsplats()
, который даже не повторяет карту. Вы уверены, что именно здесь выбрасывается исключение? Можете ли вы опубликовать свою трассировку стека? - person Artyom   schedule 10.06.2013