Рейтинг темы:
  • 0 Голос(ов) - 0 в среднем
  • 1
  • 2
  • 3
  • 4
  • 5
Анализ доступа к ArrayList
#1
Ребят, у меня бывает вылетает ошибочка, о том что идет доступ к неконкурентной версии 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 посмотрю что будет...
Ответ
#2
Используйте синхронизацию, для работы с этим объектом. Или блокировки
Ответ
#3
во время итерации коллекции вы в другом потоке её изменяете.
не плохо было бы выделять как то строки в которых ошибка.

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

И почему так сложно загуглить? Проблема по моему очень распространённая у новичков, когда только начинал сам с ней сталкивался.
[Изображение: l2nextgen.gif]
Ответ
#4
212 строка
Код:
        loop:for(SkillLearn temp : skillLearns)
Ответ
#5
Юзайте фастлист)) ему всё равно на этот момент, когда его изменяют во время использования Smile
Либо как Вам выше сказал Azagthtot.
open-team.ru
Ответ
#6
Сделал синхронизированными методы

getAvailableAllSkills
getAvaliableAllList

ничего не изменилось...
Ответ
#7
Ну тогда блокируйте их, через ReentrantLock
open-team.ru
Ответ
#8
не методы синхронизировать надо а саму коллекцию >_<

synchronized(list)
{
бла бла бла
}
Ответ
#9
тут видимо ошибка в алгоритме (это при условии что _normalSkillTree должна хранить/хранит статические данные)

PHP код:
<?php 
public Collection<SkillLearn> getAvailableAllSkills(Player player)
{
final
Collection<SkillLearn> skills;
// тут ошибка видимо
// skills = _normalSkillTree.get(player.getActiveClassId());
skills = new ArrayList<>(_normalSkillTree.get(player.getActiveClassId()));
if (
player.isAwaking())
l2jfree | M.O.R.F. | A.P.S. | Aion | GW2 | BnS
Ответ
#10
ANZO Написал:не методы синхронизировать надо а саму коллекцию >_<

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

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

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

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

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

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


Возможно похожие темы ...
Тема Автор Ответы Просмотры Последний пост
  ArrayList vs CopyOnWriteArrayList Aquanox 3 4,678 07-08-2008, 05:33 PM
Последний пост: CHIPSET

Перейти к форуму:


Пользователи, просматривающие эту тему: 2 Гость(ей)