[英]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.