Форум администраторов игровых серверов

Форум администраторов игровых серверов (https://forum.zone-game.info/TT.php)
-   Java (https://forum.zone-game.info/forumdisplay.php?f=126)
-   -   Анализ доступа к ArrayList (https://forum.zone-game.info/showthread.php?t=19022)

ALF. 03.04.2012 13:09

Анализ доступа к ArrayList
 
Ребят, у меня бывает вылетает ошибочка, о том что идет доступ к неконкурентной версии ArrayList, но в коде всё нормально.
Скорее всего где то "глубоко" идет просто вызов двух функций, которые обращаются к одному и тому же листу. Точнее вторая обращается в то время, когда первая еще не закончила с ним работу.
Вот самим ошибка к примеру
Код:

java.util.ConcurrentModificationException
        at java.util.ArrayList$Itr.checkForComodification(ArrayList.java:782)
        at java.util.ArrayList$Itr.next(ArrayList.java:754)
        at l2p.gameserver.data.xml.holder.SkillAcquireHolder.getAvaliableAllList(SkillAcquireHolder.java:212)
        at l2p.gameserver.data.xml.holder.SkillAcquireHolder.getAvailableAllSkills(SkillAcquireHolder.java:206)
        at l2p.gameserver.network.serverpackets.ExAcquirableSkillListByClass.<init>(ExAcquirableSkillListByClass.java:19)
        at l2p.gameserver.network.clientpackets.RequestSkillList.runImpl(RequestSkillList.java:25)
        at l2p.gameserver.network.clientpackets.L2GameClientPacket.run(L2GameClientPacket.java:51)
        at l2p.commons.net.nio.impl.MMOExecutableQueue.run(MMOExecutableQueue.java:38)
        at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1110)
        at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:603)
        at java.lang.Thread.run(Thread.java:636)


и сам код
Код:

        public Collection<SkillLearn> getAvailableAllSkills(Player player)
        {
                final Collection<SkillLearn> skills;
                skills = _normalSkillTree.get(player.getActiveClassId());
                if (player.isAwaking())
                {                               
                        Collection<SkillLearn> askills = _normalSkillTree.get(player.getAwakingId());
                        for (SkillLearn s : askills)
                                skills.add(s);                       
                }
                if(skills == null)
                {
                        info("skill tree for class " + player.getActiveClassId() + " is not defined !");
                        return Collections.emptyList();
                }
                return getAvaliableAllList(skills, player.getAllSkillsArray(), player.getLevel());
        }
       
        private Collection<SkillLearn> getAvaliableAllList(final Collection<SkillLearn> skillLearns, Skill[] skills, int level)
        {
                Set<SkillLearn> skillLearnMap = new HashSet<SkillLearn>();
                loop:for(SkillLearn temp : skillLearns)
                {
                        for (Skill s : skills)
                        {
                                if (temp.getId() == s.getId())
                                {
                                        if (temp.getLevel()-1 == s.getLevel())
                                        {
                                                skillLearnMap.add(temp);
                                        }
                                        continue loop;
                                }
                                if (s.isRelationSkill())
                                {
                                        for (int ds : s.getRelationSkills())
                                        {
                                                if (temp.getId() == ds)
                                                        continue loop;
                                        }
                                }
                               
                        }
                        if (temp.getLevel() == 1)
                                skillLearnMap.add(temp);
                }

                return skillLearnMap;
        }

Добавлено через 9 минут
oO
Сейчас попробую сделать пару элементов synchronized посмотрю что будет...

Azagthtot 03.04.2012 13:40

Re: Анализ доступа к ArrayList
 
Используйте синхронизацию, для работы с этим объектом. Или блокировки

bloodshed 03.04.2012 14:06

Re: Анализ доступа к ArrayList
 
во время итерации коллекции вы в другом потоке её изменяете.
не плохо было бы выделять как то строки в которых ошибка.

at l2p.gameserver.data.xml.holder.SkillAcquireHolder. getAvaliableAllList(SkillAcquireHolder.java:212) Как эту строку искать то?

И почему так сложно загуглить? Проблема по моему очень распространённая у новичков, когда только начинал сам с ней сталкивался.

ALF. 03.04.2012 14:08

Re: Анализ доступа к ArrayList
 
212 строка
Код:

                loop:for(SkillLearn temp : skillLearns)

Drizzy 03.04.2012 17:34

Re: Анализ доступа к ArrayList
 
Юзайте фастлист)) ему всё равно на этот момент, когда его изменяют во время использования :)
Либо как Вам выше сказал Azagthtot.

ALF. 03.04.2012 17:52

Re: Анализ доступа к ArrayList
 
Сделал синхронизированными методы

getAvailableAllSkills
getAvaliableAllList

ничего не изменилось...

Drizzy 03.04.2012 17:53

Re: Анализ доступа к ArrayList
 
Ну тогда блокируйте их, через ReentrantLock

ANZO 03.04.2012 18:02

Re: Анализ доступа к ArrayList
 
не методы синхронизировать надо а саму коллекцию >_<

synchronized(list)
{
бла бла бла
}

hex1r0 03.04.2012 19:32

Re: Анализ доступа к ArrayList
 
тут видимо ошибка в алгоритме (это при условии что _normalSkillTree должна хранить/хранит статические данные)

PHP код:

public Collection<SkillLearngetAvailableAllSkills(Player player)
    {
        final 
Collection<SkillLearnskills;
        
// тут ошибка видимо
        // skills = _normalSkillTree.get(player.getActiveClassId());
        
skills = new ArrayList<>(_normalSkillTree.get(player.getActiveClassId()));
        if (
player.isAwaking()) 


ALF. 05.04.2012 10:46

Re: Анализ доступа к ArrayList
 
Цитата:

Сообщение от ANZO (Сообщение 175085)
не методы синхронизировать надо а саму коллекцию >_<

synchronized(list)
{
бла бла бла
}

думаю смысла нету)
Цитата:

Если при написании какого-нибудь метода оказалось, что в блок synchronized входят все операторы этого метода, то можно просто пометить метод-словом synchronized, сделав его синхронизированным (synchronized):
Добавлено через 13 минут
Цитата:

Сообщение от hex1r0 (Сообщение 175153)
тут видимо ошибка в алгоритме (это при условии что _normalSkillTree должна хранить/хранит статические данные)

PHP код:

public Collection<SkillLearngetAvailableAllSkills(Player player)
    {
        final 
Collection<SkillLearnskills;
        
// тут ошибка видимо
        // skills = _normalSkillTree.get(player.getActiveClassId());
        
skills = new ArrayList<>(_normalSkillTree.get(player.getActiveClassId()));
        if (
player.isAwaking()) 


Это скорее всего только предотвратит NPE (Null Pointer Exeption), но не конкурентику.. )

А делать коллекцию конкурентной - не особо хочется.. Да и тут она не должна быть конкурентной.. ((


Текущее время: 08:32. Часовой пояс GMT +3.

Powered by vBulletin® Version 3.8.6
Copyright ©2000 - 2024, Jelsoft Enterprises Ltd. Перевод: zCarot