你好,而不是使用linkedlist with (reentrant lock)或使用ArrayList (with Collections.synchronizedList)我读过的,使用ConcurrentLinkedDeque将消除使用读/写锁。我想要做的是添加一个游戏角色对象,每次角色进入地图(字段)或离开地图时都会添加和删除该对象。我们可以同时让数百名玩家进入或离开任何地图......这就是我所做的private final ConcurrentLinkedDeque<User> charUsers;public Field() { this.charUsers = new ConcurrentLinkedDeque<>();}public User getUserByID(int id) { return charUsers.stream().filter(c -> c.getId() == id).findFirst().orElse(null);}public void addUser(User chr) { if (!charUsers.contains(chr)) { charUsers.add(chr); } broadcastPacket(UserPool.userEnterField(chr), chr);}public void removeUser(User chr) { charUsers.remove(chr); // or charUsers.remove();? broadcastPacket(UserPool.userLeaveField(chr), chr);}public void broadcastPacket(byte[] outPacket, User exceptChr) { charUsers.stream().filter(chr -> !chr.equals(exceptChr)).forEach( chr -> chr.getClient().getSession().send(outPacket) );}我有点担心并发性,我读过它ConcurrentLinkedDeque在多线程环境中是线程安全的,但是在使用迭代器时它的一致性很弱。我试图避免任何ConcurrentModificationExceptions.如果不是这种情况,我会更好地使用 sync.List withArrayList或 aLinkedList吗?与此游戏设计相关的一个附带问题,我基于一个相当古老的基于 Java 的游戏,当时我相信该游戏使用了 Java 1.5,而他们hashmaps改为添加/删除游戏的实体/对象(角色、地图、怪物,NPC)。我相信即使使用ReentrantLock. 所以我正在尝试不同的方法。(尽管该问题可能还有其他因素,但我认为这是主要因素)。
1 回答
皈依舞
TA贡献1851条经验 获得超3个赞
因此,从您发布的代码来看,您使用的似乎charUsers
只是跟踪当前地图中的所有内容。您正在扫描集合以查找实体,并且您正在添加和删除实体。并且您担心对集合的并发访问?一致性怎么样,你担心吗?例如,线程 A 添加一个事物,线程 B 删除它,然后线程 A 试图表现得好像该事物仍在集合中一样;你关心?这是并发问题的一部分。
现在,如果您想要的是一个列表,并且您将一直添加和删除节点,而不必在末尾添加和删除节点,那么链表就很棒。但是如果您想在集合中搜索特定项目并且您通常不关心所有项目,那么链表就很糟糕。毕竟,也许您想要一个映射——ConcurrentHashMap,其中键是事物的 ID,值是事物。每次搜索一个东西时,你都必须遍历该列表直到找到它,这最终是一个 O(N) 问题,对,当你遍历该列表时,你会面临并发修改(也许你想要一个 CopyOnWriteArrayList,如果你有内存要烧的话)。
我同意其他评论者的观点,即这个问题可能太宽泛而无法得到可靠的是/否答案。有许多不同的方法可以最小化同步和并发访问的成本,但它们都是由系统目标驱动的。一种方法可能对一个系统很好,但对另一个系统很糟糕。
我建议做一些幼稚和可行的事情并对其进行分析或以其他方式根据您的期望结果衡量其性能。这可以让您看到真正需要优化的地方。
添加回答
举报
0/150
提交
取消