问题描述
对于一个班级项目,我正在使用并发HashMap来包含活动用户及其连接详细信息的列表。多个线程应该能够获取所有活动用户的列表,其中5个线程能够修改hashMap。当我对其进行测试时,它似乎可以工作,但是我不知道线程是否被阻塞并且系统是否足够快。
- 我想封装并发HashMap,但是我不知道这是否会阻止其并发?
-
我还希望哈希表只有一个版本,所以我将该类设为枚举,很糟糕,只是让 main 可以创建它? - 我不希望其他线程修改hashMap,所以我不传递集合/迭代器。有没有没有删除就可以传递收藏的方法吗?
- (新)我在CoolFeature中调用了两种方法,一种是阻塞,另一种不是。两者都可以有自己的位置。论文有什么问题吗?
我们正在使用Akka Actors创建线程并处理并发性,下面是我的简化代码。这不是分配问题,只是我作为项目一部分创建的内容的一部分。
编辑:我更改了代码,拥有一个不依赖Akka的解决方案将是一件好事,这样其他人可以找到有用的答案。
package server.management;
public class Sessions {
static final ConcurrentHashMap<Integer,Id<User>> sessions = new concurrentHashMap<>();
private Sessions() { }
}
public class SessionManager {
public static void create(int connection,Id<User> userId) {
// checks
Sessions.sessions.put(connection,userId);
}
public static Id<User> getUser(int connection) {
Id<User> userId = Sessions.sessions.get(connection);
return userId;
}
public static ArrayList<Id<User>> getActiveUsers() {
ArrayList<Id<User>> list = new ArrayList<>();
// Don't pass the sessions.values() directly because the Map can be modified.
for (Id<User> userId : Sessions.sessions.values()) {
list.add(userId);
}
return list;
}
// other methods
}
/* Another thread/akka actor class */
package server;
import server.management.SessionManager;
public class CoolFeature extends AbstractActor {
...
Id<User> client = SessionManager.getUser(1023);
// do stuff
CompletableFuture<ArrayList<Id<User>>> futureList =
CompletableFuture.supplyAsync(SessionManager::getActiveUsers);
// do stuff
ArrayList<Id<User>> list = futureList.get();
// do stuff
}
解决方法
使用akka actor,您可以将正常Map放在actor中作为状态,而不必担心并发访问,因为使用actor模型,actor一次只能处理一条消息。您可以执行以下操作。该代码在Scala中,但您明白我的想法。
object Manager {
case class Get(id: Int)
case object GetActive
case class Create(connId: Int,userId: Int)
}
class Manager extends Actor {
import Manager._
val sessions = mutable.Map[Int,Int].empty
override def receive = {
case Get(id) => sessions.get(id)
case GetActive => sessions.values
case Create(connId,userId) => sessions += (connId -> userId)
}
}
如果您有任何问题,请告诉我。