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

Форум администраторов игровых серверов (https://forum.zone-game.info/TT.php)
-   Работа со скриптами (https://forum.zone-game.info/forumdisplay.php?f=37)
-   -   LinkedHashMap в эффекте (https://forum.zone-game.info/showthread.php?t=41881)

finfan 25.12.2016 01:03

LinkedHashMap в эффекте
 
При onStart() эффекта, в LinkedHashMap добавляет ключ-значение.
При onExit() эффекта, ключ-значение оттуда удаляется.

Словлю ли я Exception?, если onStart() по времени, вызовется одновременно с onExit() и карта, попробует добавить и удалить ключ-значение? Что вообще здесь происходит?

Может стоит использовать в таких случаях ConcurrentHashMap?

Mangol 25.12.2016 02:48

Re: LinkedHashMap в эффекте
 
ConcurrentModificationException можно словить лишь в том случае, если во время перебора forEach, Iterator, удалить, добавить, либо еще сделать какую либо операцию по изменению элементов. Она приведет к ошибке.

P.S. Зачем нужна именно эта мапа ?) Для более ясного ответа, нужно знать - мапа работает на 1-го игрока, либо глобально на эффект ?

finfan 25.12.2016 04:01

Re: LinkedHashMap в эффекте
 
Цитата:

Сообщение от Mangol (Сообщение 422166)
ConcurrentModificationException можно словить лишь в том случае, если во время перебора forEach, Iterator, удалить, добавить, либо еще сделать какую либо операцию по изменению элементов. Она приведет к ошибке.

P.S. Зачем нужна именно эта мапа ?) Для более ясного ответа, нужно знать - мапа работает на 1-го игрока, либо глобально на эффект ?

Мапа работает на одного игрока (один игрок управляет своей мапой) и содержит в себе данные на других (на ком лежит эффект). Накладывая эффект на очередную жертву, мапа обновляется и удаляется в зависимости от максимального окл-ва наложений эффекта:
Например, если эффект можно наложить лишь на 3 цели - одним кастером. При наложении на 4-ую, из мапы убирается 1 товарищ (и эффект с него тоже снимается) и добавляется другой.

Anikey 25.12.2016 08:42

Re: LinkedHashMap в эффекте
 
Цитата:

Сообщение от finfan (Сообщение 422163)
Словлю ли я Exception?, если onStart() по времени, вызовется одновременно с onExit() и карта, попробует добавить и удалить ключ-значение? Что вообще здесь происходит?

Нет, не словишь.
Если нечего удалять вернет null, как и в случае putIfAbsent, etc...
Как подметил Mangol ConcurrentModificationException - мы можем выхватить, только если удаляем напрямую из коллекции - во время работы итератора. Нужно использовать метод итератора remove(), чтобы было корректно.

Mangol 25.12.2016 11:22

Re: LinkedHashMap в эффекте
 
Цитата:

Сообщение от Anikey (Сообщение 422170)
Нет, не словишь.
Если нечего удалять вернет null, как и в случае putIfAbsent, etc...
Как подметил Mangol ConcurrentModificationException - мы можем выхватить, только если удаляем напрямую из коллекции - во время работы итератора. Нужно использовать метод итератора remove(), чтобы было корректно.

remove(); Итератора не спасет, все равно получим ConcurrentModificationException.
П.1 Не только удаляем, при любом добавлении либо удалении, получим ConcurrentModificationException.
На сколько я помню там есть проверка.
int mod=correctMod;
if(mod != correctMod)
привет ConcurrentModificationException;

Добавлено через 10 минут
Цитата:

Сообщение от finfan (Сообщение 422167)
Мапа работает на одного игрока (один игрок управляет своей мапой) и содержит в себе данные на других (на ком лежит эффект). Накладывая эффект на очередную жертву, мапа обновляется и удаляется в зависимости от максимального окл-ва наложений эффекта:
Например, если эффект можно наложить лишь на 3 цели - одним кастером. При наложении на 4-ую, из мапы убирается 1 товарищ (и эффект с него тоже снимается) и добавляется другой.

А вообще.... Если боишься что влетит 2 потока, и что то не правильно добавится - удалиться. Используй ConcurrentHashMap<>();

Ну если на крайний случай map = HashMap<>();
//write code;
synchronized(map) // mutex
{
//write code;
}
//write code;

Hack 25.12.2016 12:18

Re: LinkedHashMap в эффекте
 
Если мапка не используется в каких либо итераторах, то можешь смело добавлять и тереть в ней сколько влезет.
Если же задействована в итераторе (не важно по ключам, значениям или парам), тогда уже нужен пакет concurency, либо синхронизация.
Вообще любое изменяемое хранилище, к которому могут получить доступ несколько потоков по дефолту должно быть конкурентным.

Anikey 25.12.2016 12:19

Re: LinkedHashMap в эффекте
 
Mangol,
PHP код:

final LinkedHashMap<ObjectObjectlinked = new LinkedHashMap<>();
linked.put("1""1");
linked.put("2""2");
linked.put("3""3"); 

Следующие выражения выбьют ошибку:
Java 8:
PHP код:

linked.entrySet().stream().filter((i) -> ("3".equals(i.getKey()))).forEachOrdered((i) -> {
     
linked.remove(i.getKey());
}); 

Ниже 8 версии:
PHP код:

for (Entry<ObjectObjectlinked.entrySet()) {
    if (
"3".equals(i.getKey())) {
         
linked.remove(i.getKey());
    }


А вот это решение отработает правильно и без ошибок:
PHP код:

final Iterator<Entry<ObjectObject>> linked.entrySet().iterator();
while (
i.hasNext()) {
    if (
"3".equals(i.next().getKey())) {
       
i.remove();
    }



Mangol 25.12.2016 12:29

Re: LinkedHashMap в эффекте
 
Цитата:

Сообщение от Anikey (Сообщение 422175)
Mangol,
PHP код:

final LinkedHashMap<ObjectObjectlinked = new LinkedHashMap<>();
linked.put("1""1");
linked.put("2""2");
linked.put("3""3"); 

Следующие выражения выбьют ошибку:
Java 8:
PHP код:

linked.entrySet().stream().filter((i) -> ("3".equals(i.getKey()))).forEachOrdered((i) -> {
     
linked.remove(i.getKey());
}); 

Ниже 8 версии:
PHP код:

for (Entry<ObjectObjectlinked.entrySet()) {
    if (
"3".equals(i.getKey())) {
         
linked.remove(i.getKey());
    }


А вот это решение отработает правильно и без ошибок:
PHP код:

[COLOR="red"]final Iterator<Entry<ObjectObject>> linked.entrySet().iterator();
while (
i.hasNext()) {
    if (
"3".equals(i.next().getKey())) {
       
i.remove();
    }
}[/
COLOR


if ("2".equals(i.next().getKey())) {
i.remove();
}

Сделай 2-ое удаление :redlol:

Anikey 25.12.2016 12:36

Re: LinkedHashMap в эффекте
 
Цитата:

Сообщение от Mangol (Сообщение 422176)
Сделай 2-ое удаление

Даже в разном порядке:
PHP код:

final Iterator<Entry<ObjectObject>> linked.entrySet().iterator();
    while (
i.hasNext()) {
       switch((String)
i.next().getKey()) {
           case 
"2":
           case 
"1":
               
i.remove();
               break;
     }



Mangol 25.12.2016 12:54

Re: LinkedHashMap в эффекте
 
Цитата:

Сообщение от Anikey (Сообщение 422177)
Даже в разном порядке:
PHP код:

final Iterator<Entry<ObjectObject>> linked.entrySet().iterator();
    while (
i.hasNext()) {
       switch((String)
i.next().getKey()) {
           case 
"2":
           case 
"1":
               
i.remove();
               break;
     }



PHP код:

        public final boolean remove(Object o) {
            if (o instanceof Map.Entry) {
                Map.Entry<?,?> e = (Map.Entry<?,?>) o;
                Object key = e.getKey();
                Object value = e.getValue();
                return removeNode(hash(key), key, value, true, true) != null;
            }
            return false;
        }

Код из явки действительно поддерживает это. :)

Но есть побочные эффекты, такие как
PHP код:

    public Set<Map.Entry<K,V>> entrySet() {
       
Set<Map.Entry<K,V>> es;
        return (
es entrySet) == null ? (entrySet = new LinkedEntrySet()) : es;
    }

    final class 
LinkedEntrySet extends AbstractSet<Map.Entry<K,V>> {
        public final 
int size()                 { return size; }
        public final 
void clear()               { LinkedHashMap.this.clear(); }
        public final 
Iterator<Map.Entry<K,V>> iterator() {
            return new 
LinkedEntryIterator();
        }
    final class 
LinkedEntryIterator extends LinkedHashIterator
        
implements Iterator<Map.Entry<K,V>> {
        public final 
Map.Entry<K,Vnext() { return nextNode(); }
    } 




PHP код:

        final LinkedHashMap.Entry<K,VnextNode() {
            
LinkedHashMap.Entry<K,Vnext;
            if (
modCount != expectedModCount)
                throw new 
ConcurrentModificationException();
            if (
== null)
                throw new 
NoSuchElementException();
            
current e;
            
next e.after;
            return 
e;
        } 



Если в хранилище залетело какой то объект во время

while (i.hasNext()) {

switch((String)i.next().getKey()) {


Получим ConcurrentModification и опять же курим.
Как я сказал выше, во время доступа побочного потока если такой имеется, вызывать итератор, либо forEach методы не корректно, получим кучу соплей на выходе.

finfan 25.12.2016 14:18

Re: LinkedHashMap в эффекте
 
Спасибоу за разъяснения, в дальнейшем заюзаю конкурент хеш мэп, когда сделаю возможность эффектам: "Данный эффект может быть наложен одновременно только на одну/две/три и т.д. целей."
Быстро, оперативно и чётко запуляли ответами, класс ;D.

nn03 27.12.2016 04:15

Re: LinkedHashMap в эффекте
 
Ты пытаешься реализовать что-то подобное радару из ревелейшен ? Интересно просто :)

finfan 27.12.2016 06:21

Re: LinkedHashMap в эффекте
 
Цитата:

Сообщение от nn03 (Сообщение 422252)
Ты пытаешься реализовать что-то подобное радару из ревелейшен ? Интересно просто :)

Black Mark - метит мудилу. Следующее использовании Shadow Step перенесёт вас к отмеченной цели... etc.
Black List - позволяет метить до трёх целей подряд.

А потом мы можем переместиться к любой из этих трёх целей. Мапа нужна была для второй абилы.

nn03 27.12.2016 16:35

Re: LinkedHashMap в эффекте
 
Цитата:

Сообщение от finfan (Сообщение 422256)
Black Mark - метит мудилу. Следующее использовании Shadow Step перенесёт вас к отмеченной цели... etc.
Black List - позволяет метить до трёх целей подряд.

А потом мы можем переместиться к любой из этих трёх целей. Мапа нужна была для второй абилы.

ухты прикольно, но тут веть есть много нюансов, расстояние, текстуры ...

finfan 27.12.2016 16:41

Re: LinkedHashMap в эффекте
 
Цитата:

Сообщение от nn03 (Сообщение 422281)
ухты прикольно, но тут веть есть много нюансов, расстояние, текстуры ...

Эти ньюансы я уже пробил как следует и внёс необходимые правки, теперь, обидчика AW - будет ждать акт возмездия.

nn03 27.12.2016 17:57

Re: LinkedHashMap в эффекте
 
Цитата:

Сообщение от finfan (Сообщение 422284)
Эти ньюансы я уже пробил как следует и внёс необходимые правки, теперь, обидчика AW - будет ждать акт возмездия.

как доделаешь , сними мув, интересно посмотреть очень :)

krisadr 05.01.2017 16:01

Re: LinkedHashMap в эффекте
 
Лично мое мнение по поводу любых коллекций и многопоточности.
используйте блокировки, причем использовать их нужно там где существует возможность вхождения нескольких потоков в чтение и запись.
А использование Concurrent на мой взгяд - костыль. Ибо при записи создается копия коллекции... что при определенных обстоятельствах может повести за собой баги или даже дюп.
Код:

Чтение
locker.enterReadLock();
Тут операции чтения из коллекции
locker.exitReadLock();

Запись
locker.enterWriteLock();
Тут операции записи коллекции (добавление\удаление)
locker.exitWriteLock();

Не знаю как в java но в c# реализация локера следующая
Код:

using System.Threading;

namespace Utils.Locks
{
    public sealed class ReadWriteLockerPro
    {

        private ManualResetEvent writeLock = new ManualResetEvent(true);
        private ManualResetEvent readLock = new ManualResetEvent(true);
        private int readers = 0;

        public void enterWriteLock()
        {
            readLock.WaitOne();
            writeLock.Reset();
        }
        public void exitWriteLock()
        {
            writeLock.Set();
        }
        public void enterReadLock()
        {
            writeLock.WaitOne();
            readLock.Reset();
            Interlocked.Increment(ref readers);
        }
        public void exitReadLock()
        {
            Interlocked.Decrement(ref readers);
            if (readers == 0)
                readLock.Set();
        }
    }
}

Суть - Читатели могут(параллельно) читать до тех пор пока в очередь не зайдет писатель. Если в момент вхождения писателя не все читатели закончили чтение писатель ждет пока читатели закончат чтение, Но новые читатели уже не могут читать. Как читатели закончили - писатель начинает писать. Если другой писатель (Практически исключено. Если так происходит - значит ваша архитектура - х**ня.) входит, то он ждет пока предыдущий писатель закончит писать. Как только писатели закончили писанину - разрешаем читателям, которые были в очереди - читать дальше.
PS удалять элементы коллекции в цикле итерации по самой же коллекции - нельзя. Выход - те элементы которые нужно удалить в цикле помещаем в коллекцию удаления. Прим ArrayList<item> deletedList;
и потом уже после цикла главной коллекции - добавляем цикл удаления если deletedList.count > 0. и в нем уже удаляем элементы из главной коллекции а после deletedList.clear();


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

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