[英]List in ConcurrentHashMap
public static ConcurrentHashMap<Integer,Session> USER_SESSIONS...
一切正常。 但是如果允许系统被授权两个具有相同用户ID的会话呢? 嗯,大约有两台PC坐在同一个帐户下,但会话不同。 试图这样做:
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!>
}
}
当然,可以从不同的线程调用所有这些方法,并且我得到与List相关的错误。 这很自然,因为虽然我有foreach-list会话可以通过removeUser从另一个线程中删除。 该怎么办? 如何使 - 在所有线程的列表中工作列表等待它占用线程完成后呢? 然而这样做:)
public static ConcurrentHashMap<Integer,ConcurrentHashMap<Session,Session>> USER_SESSIONS
由于ConcurrentHashMap线程安全。 但我认为这是一个歪曲的决定。 非常感谢您的帮助!
PS:JRE 1. 6
抱歉我的英语。
您可以使用List myList = Collections.synchronizedList(new ArrayList<String>());
如果您不想使用CopyOnWriteArrayList。
您唯一需要记住的是, 必须同步代码,您将在列表上进行迭代。 您可以在此处查看更多信息: Collections.synchronizedList和synchronized
在这种情况下,使用线程安全列表仍然不足以防止竞争条件。 同时有两个addUser调用可能会覆盖彼此的put。 另外,在检查大小和remoeUser中的remove调用之间可能会发生添加。
你需要这样的东西(未经测试)。 此代码假定在调用它之前不会删除会话。
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);
}
}
}
}
您可以尝试在您的情况下使用CopyOnWriteArrayList或CopyOnWriteArraySet 。
使用List myList = Collections.synchronizedList(new ArrayList<String>());
会更好
但是如果有比read更多的读操作,你也可以使用可以安全迭代的CopyOnWriteArrayList
。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.