Гость
Целевая тема:
Создать новую тему:
Автор:
Форумы / Java [игнор отключен] [закрыт для гостей] / ConcurrentHashMap и List / 25 сообщений из 33, страница 1 из 2
06.12.2013, 05:20
    #38491191
GorloPavel
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
ConcurrentHashMap и List
Здравствуйте. Такое дело.
Код: java
1.
public static ConcurrentHashMap<Integer,Session> USER_SESSIONS...


В этом HashMap-e находятся некие сессии где ключ это ID пользователя. Когда пользователь отключается сессия удаляется.
Код: java
1.
USER_SESSIONS.remove(mUserId);


Все отлично работает. Но как быть если в системе разрешено быть авторизированным двум сессиям с одним и тем же ID пользователя? Ну то есть грубо говоря на двух ПК в сидят под одной и той же учеткой, но при этом сессии разные.
Пробовал сделать так:
Код: java
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
16.
17.
18.
19.
20.
21.
22.
23.
24.
25.
26.
27.
28.
29.
30.
31.
32.
33.
34.
35.
ConcurrentHashMap<Integer,List<Session>> USER_SESSIONS....

......................

private void addUser(Session session){
   List<Session> userSessions = Server.USER_SESSIONS.get(session.mUserId);
   
   if(userSessions==null){
       userSessions = new List<Session>();
       userSessions.add(session);
       Server.USER_SESSIONS.put(session.getUserId(),userSessions);
   }else{
       userSessions.add(session);
   }
}

private void removeUser(Session session){
   List<Session> userSessions = Server.USER_SESSIONS.get(session.mUserId);
   
   if(userSessions==null){
        userSessions.remove(session);
        if(userSessions.size()==0)
        {
            Server.USER_SESSIONS.remove(session.getUserId());
        }
   }
}

.....................
private void workWithUsers(int userId){
     for(Session session : Server.USER_SESSIONS.get(userId))
    {
         <какие-то действия>
    }
}



Естественно все эти методы могут вызываться из разных потоков, и я получаю ошибки связанные с List<Session>. И это естественно, потому что пока я foreach-у список сессия может быть удалена методом removeUser из другого потока. Как быть? Как сделать так что-бы при работе со списком List<Session> все потоки ждали пока занимающий его поток не закончит с ним работу? Пока сделал так :)
Код: java
1.
public static ConcurrentHashMap<Integer,ConcurrentHashMap<Session,Session>> USER_SESSIONS 


Так как ConcurrentHashMap потокобезопасен. Но мне кажется это кривое решение. Заранее огромное спасибо за помощь!

P.S: JRE 1. 6
...
Рейтинг: 0 / 0
06.12.2013, 07:59
    #38491224
GorloPavel
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
ConcurrentHashMap и List
Как я понял CopyOnWriteList мне не подходит. Ведь при каждом изменении производится копирование массива и потом подменяется ссылка. Но что будет если в момент удаления произойдет добавление? Или я что-то не понимаю. Просто попробовал использовать CopyOnWriteList и сразу сильно возрасло потребление памяти и оно постоянно растет.
...
Рейтинг: 0 / 0
06.12.2013, 09:21
    #38491272
am_sasa
Гость
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
ConcurrentHashMap и List
GorloPavel,

не понятно зачем HashMap - id usera дублируется, он же в сессии есть, может HashSet хватит?
у меня так
Код: java
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
 public void addSession(HttpSession s) {
            this.sessions.add(s);
            s.setAttribute(SessionBug.class.getName(), new SessionBug());
        }

        public void removeSession(HttpSession s) {
            this.sessions.remove(s);
        }

        public Collection<HttpSession> getSessions(){
           return Collections.unmodifiableCollection(this.sessions);
        }


вот это должно помочь Collections.unmodifiableCollection(USER_SESSIONS)
...
Рейтинг: 0 / 0
06.12.2013, 09:28
    #38491282
cdtyjv
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
ConcurrentHashMap и List
am_sasaвот это должно помочь Collections.unmodifiableCollection(USER_SESSIONS) Это никак не может помочь пользователю, так как ему необходимо эту коллекцию изменять, а unmodifiableCollection запрещает удаление.
...
Рейтинг: 0 / 0
06.12.2013, 09:32
    #38491289
cdtyjv
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
ConcurrentHashMap и List
GorloPavel ,
CopyOnWriteArrayList - нормальное решение, когда у вас много чтений, но мало записей. Память у вас течет из-за бага где-то у вас, а не из-за на него.
Если CopyOnWriteArrayList не устраивает, то используйте другую коллекцию из java.util.concurrent, коих очень много - Set, Queue, Deque - в зависимости от того, что вам больше подходит.
...
Рейтинг: 0 / 0
06.12.2013, 09:42
    #38491301
am_sasa
Гость
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
ConcurrentHashMap и List
cdtyjv,

в каком месте удаление?
Код: java
1.
2.
3.
4.
5.
6.
private void workWithUsers(int userId){
     for(Session session : Server.USER_SESSIONS.get(userId))
    {
         <какие-то действия>
    }
}
...
Рейтинг: 0 / 0
06.12.2013, 10:00
    #38491332
cdtyjv
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
ConcurrentHashMap и List
am_sasa ,
Ну вы проблему автора читали? :-) Ему нужно конкурентно обновлять коллекцию. А вы ему на это отвечаете: "Вам должен помочь Collections.unmodifiableList". Вопрос: как он ему поможет?
Collections.unmodifiable* полезены только в двух случаях:
1) Это публичный API, которым будет пользоваться хрен знает кто.
2) Это не публичный API, но разработчик все равно хочет перестраховаться, использую unmodifiableList в качестве своеобразного assert.

К проблема конкуретного доступа к коллекциям Collections.unmodifiable* отношения вообще не имеет.
...
Рейтинг: 0 / 0
06.12.2013, 11:25
    #38491447
Blazkowicz
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
ConcurrentHashMap и List
Если нужно разрашить множественные сессии под одним аккаунтом, то нужно максимально везде заменить userId на sessionId:
Map<SessionId, Session>
А для каждой операции с userId, нужно хорошенько подумать, почему там нужен именно userId, а не sessionId. И свести такие операции к минимуму. Ведь юзер работает в двух РАЗНЫХ сессиях и он не ожидает что в обоих сессиях будет идентичное состояние, только потому что внутри всё равно всё привязано к userId.
...
Рейтинг: 0 / 0
06.12.2013, 13:58
    #38491756
GorloPavel
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
ConcurrentHashMap и List
Может мне кто-нибудь объяснить? Как я понимаю в этом случае remove и add потокобезопасны? Т.е если какой-то поток добавляет что-то в лист, то поток который хочет удалить будет ожидать завершения удаления и наоборот? А чтобы синхронизировать и перебор(все ждут пока идет перебор) нужно делать так?
Код: java
1.
2.
3.
4.
5.
6.
7.
Collection c = Collections.synchronizedCollection(myCollection);
     ...
  synchronized(c) {
      Iterator i = c.iterator(); // Must be in the synchronized block
      while (i.hasNext())
         foo(i.next());
  }
...
Рейтинг: 0 / 0
06.12.2013, 14:00
    #38491759
GorloPavel
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
ConcurrentHashMap и List
BlazkowiczЕсли нужно разрашить множественные сессии под одним аккаунтом, то нужно максимально везде заменить userId на sessionId:
Map<SessionId, Session>
А для каждой операции с userId, нужно хорошенько подумать, почему там нужен именно userId, а не sessionId. И свести такие операции к минимуму. Ведь юзер работает в двух РАЗНЫХ сессиях и он не ожидает что в обоих сессиях будет идентичное состояние, только потому что внутри всё равно всё привязано к userId.
К моему приложению это не подходит. Мне нужно именно синхронно редактировать или читать список.
...
Рейтинг: 0 / 0
06.12.2013, 14:51
    #38491883
GorloPavel
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
ConcurrentHashMap и List
cdtyjv GorloPavel ,
CopyOnWriteArrayList - нормальное решение, когда у вас много чтений, но мало записей. Память у вас течет из-за бага где-то у вас, а не из-за на него.
Да нет бага. Просто заменяю на
Код: java
1.
public static ConcurrentHashMap<Integer,ConcurrentHashMap<Session,Session>> USER_SESSIONS 


и памяти на 15-20% меньше жрет приложение.
...
Рейтинг: 0 / 0
06.12.2013, 14:53
    #38491885
Blazkowicz
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
ConcurrentHashMap и List
CopyOnWriteArrayList очень агресивно использует память, что, как бы, следует из его названия и принципа работы.
...
Рейтинг: 0 / 0
06.12.2013, 15:25
    #38491947
Petro123
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
ConcurrentHashMap и List
GorloPavelBlazkowiczЕсли нужно разрашить множественные сессии под одним аккаунтом, то нужно максимально везде заменить userId на sessionId:
Map<SessionId, Session>
А для каждой операции с userId, нужно хорошенько подумать, почему там нужен именно userId, а не sessionId. И свести такие операции к минимуму. Ведь юзер работает в двух РАЗНЫХ сессиях и он не ожидает что в обоих сессиях будет идентичное состояние, только потому что внутри всё равно всё привязано к userId.
К моему приложению это не подходит. Мне нужно именно синхронно редактировать или читать список.
не очень понял ответ Blazkowicz'у.
Разве 2 пользователя под одним именем но на разных компах не A синхронно работают?
...
Рейтинг: 0 / 0
06.12.2013, 15:38
    #38491968
GorloPavel
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
ConcurrentHashMap и List
Petro123GorloPavelпропущено...
К моему приложению это не подходит. Мне нужно именно синхронно редактировать или читать список.
не очень понял ответ Blazkowicz'у.
Разве 2 пользователя под одним именем но на разных компах не A синхронно работают?

Асинхронно. Но сервер с списком сессий должен работать синхронно. Долго объяснять. Вообщем мне не подходит это решение. Я уже думал над этим. Пожалуйста прокомментируйте это сообщение 15252928
...
Рейтинг: 0 / 0
06.12.2013, 15:53
    #38491990
Petro123
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
ConcurrentHashMap и List
GorloPavel,
не очень понял, зачем бегать по списку в конкурентном окружении?
...
Рейтинг: 0 / 0
06.12.2013, 15:54
    #38491993
Petro123
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
ConcurrentHashMap и List
GorloPavel,
и приведи конкретный код с ошибкой минимальный
...
Рейтинг: 0 / 0
06.12.2013, 15:59
    #38491999
GorloPavel
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
ConcurrentHashMap и List
Petro123GorloPavel,
и приведи конкретный код с ошибкой минимальный
Ну как же. А если во время foreach другой поток удалит из списка элемент? Пользователь отключается, а в этот момент сервер пробегает по списку и рассылает пользователям под этой учеткой "ПРИВЕТ ТОВАРИЩ!" :)
...
Рейтинг: 0 / 0
06.12.2013, 16:08
    #38492017
забыл ник
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
ConcurrentHashMap и List
GorloPavelPetro123GorloPavel,
и приведи конкретный код с ошибкой минимальный
Ну как же. А если во время foreach другой поток удалит из списка элемент? Пользователь отключается, а в этот момент сервер пробегает по списку и рассылает пользователям под этой учеткой "ПРИВЕТ ТОВАРИЩ!" :)

Так не критично же? Ну а что вас спасет если вы успели пробежать по циклу, но клиент отосединился как раз когда вы посылаете сообщение? Выдуманно как-то смотрится проблема.
...
Рейтинг: 0 / 0
06.12.2013, 16:13
    #38492026
Petro123
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
ConcurrentHashMap и List
забыл ник,
+1
...
Рейтинг: 0 / 0
06.12.2013, 16:37
    #38492067
GorloPavel
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
ConcurrentHashMap и List
забыл никGorloPavelпропущено...

Ну как же. А если во время foreach другой поток удалит из списка элемент? Пользователь отключается, а в этот момент сервер пробегает по списку и рассылает пользователям под этой учеткой "ПРИВЕТ ТОВАРИЩ!" :)

Так не критично же? Ну а что вас спасет если вы успели пробежать по циклу, но клиент отосединился как раз когда вы посылаете сообщение? Выдуманно как-то смотрится проблема.
А null pointer exception? Ну и вообще изменилась же коллекция, а я тут форичу. Вообщем с CopyOnWriteArrayList работает, но жрет память. С
Код: java
1.
public static ConcurrentHashMap<Integer,ConcurrentHashMap<Session,Session>> USER_SESSIONS 

вообще все отлично и памяти навалом и работает хорошо. Вот как-нибудь сделать такой же список.
...
Рейтинг: 0 / 0
06.12.2013, 16:38
    #38492070
GorloPavel
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
ConcurrentHashMap и List
Последний вариант мне кажется кривым, но он замечательно работает.
...
Рейтинг: 0 / 0
06.12.2013, 16:39
    #38492072
GorloPavel
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
ConcurrentHashMap и List
Попробовал так
Код: java
1.
Collections.synchronizedCollection

- вообще все повисло в какой-то момент, видимо где-то дедлочит.
...
Рейтинг: 0 / 0
06.12.2013, 16:43
    #38492076
Blazkowicz
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
ConcurrentHashMap и List
GorloPavelПопробовал так
Код: java
1.
Collections.synchronizedCollection

- вообще все повисло в какой-то момент, видимо где-то дедлочит.
Использование synchronized в многопоточных приложениях это не только потенциальные взаимоблокировки но и удар по производительности системы в целом. Особено учитывая тот факт что это у вас центральное состояние всех пользователей.
...
Рейтинг: 0 / 0
06.12.2013, 16:46
    #38492082
Petro123
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
ConcurrentHashMap и List
GorloPavelдедлочит
OFF
осталось взять Оракл - неблокировочник))))
...
Рейтинг: 0 / 0
06.12.2013, 16:47
    #38492086
Petro123
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
ConcurrentHashMap и List
GorloPavelа я тут форичу
зачем?
Сделай список по уникальному ключику
...
Рейтинг: 0 / 0
Форумы / Java [игнор отключен] [закрыт для гостей] / ConcurrentHashMap и List / 25 сообщений из 33, страница 1 из 2
Найденые пользователи ...
Разблокировать пользователей ...
Читали форум (0):
Пользователи онлайн (0):
x
x
Закрыть


Просмотр
0 / 0
Close
Debug Console [Select Text]