简体   繁体   中英

List in ConcurrentHashMap

public static ConcurrentHashMap<Integer,Session> USER_SESSIONS...    

Everything works fine. But what if the system is allowed to be authorized two sessions with the same user ID? Well, that is roughly two PCs sitting under the same account, but different session. Tried to do so:

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))
    {
       <do it!>
    }
}

Naturally, all these methods can be called from different threads, and I'm getting errors related to List . And this is natural, because while I have foreach-list session can be removed by removeUser from another thread. What to do? How to make so that-be at work with a list of all the threads List waited until it occupies the thread is finished with it? Yet done so :)

public static ConcurrentHashMap<Integer,ConcurrentHashMap<Session,Session>> USER_SESSIONS

Since ConcurrentHashMap thread safe. But I think it's crooked decision. Many thanks in advance for your help!

PS: JRE 1. 6

Please sorry for my English.

You could use List myList = Collections.synchronizedList(new ArrayList<String>()); if you don't want to use CopyOnWriteArrayList.

The only thing you need to have in mind is that it is mandatory to synchronized the code where you will be iterating over the list. You can see more info here: Collections.synchronizedList and synchronized

Using a thread safe list is still not enough to prevent race conditions in this case. There's a possibility that two addUser calls at the same time may overwrite each other's puts. Also an add could happen between the check for size and the remove call in remoeUser.

You need something like this (not tested). This code assumes that a session will not be removed before a call to it's add.

    private void addUser(Session session) {
    while (true) {
        List<Session> userSessions = Collections.synchronizedList(new ArrayList<Session>());
        List<Session> oldSessions = USER_SESSIONS.putIfAbsent(session.mUserId, userSessions);
        if (oldSessions != null) {
            userSessions = oldSessions;
        }
        userSessions.add(session);

        // want to make sure the map still contains this list and not another
        // so checking references
        // this could be false if the list was removed since the call to putIfAbsent
        if (userSessions == USER_SESSIONS.get(session.mUserId)) {
            break;
        }
    }
}

private void removeUser(Session session) {
    List<Session> userSessions = USER_SESSIONS.get(session.mUserId);
    if (userSessions != null) {
        // make whole operation synchronized to make sure a new session is not added
        // after the check for empty
        synchronized (userSessions) {
            userSessions.remove(session);
            if (userSessions.isEmpty()) {
                USER_SESSIONS.remove(session.mUserId);
            }
        }
    }
}

您可以尝试在您的情况下使用CopyOnWriteArrayListCopyOnWriteArraySet

use List myList = Collections.synchronizedList(new ArrayList<String>()); will be better
But if there is much more read operation than write, you can also use CopyOnWriteArrayList which is safe to iterate.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM