java - ConcurrentLinkedDeque的正确使用

标签 java

Hello,而不是使用 linkedlist with (reentrant lock)或使用ArrayList (with Collections.synchronizedList)我使用 ConcurrentLinkedDeque 读到了这一点将消除使用读/写锁。我想做的是添加一个游戏角色对象,每次角色进入 map (字段)或离开 map 时都会添加和删除该对象。我们可以让数百名玩家同时进入或离开任何 map ......

这就是我所做的

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 .

如果不是这种情况,我最好使用 ArrayList 的sync.List或LinkedList

与这个游戏设计相关的一个附带问题,我是基于一个相当古老的基于 java 的游戏,我相信当时使用了 java 1.5,他们使用了 hashmaps而是添加/删除游戏的实体/对象(角色、 map 、生物、npc)。我相信即使使用 ReentrantLock 也存在一些并发问题。所以我正在尝试一种不同的方法。 (虽然这个问题可能还有其他因素,但我认为这是主要因素)。

最佳答案

因此,从您发布的代码来看,您使用 charUsers 的目的似乎只是跟踪当前 map 中的所有内容。您正在扫描集合以查找实体,并且正在添加和删除实体。您担心对集合的并发访问吗?一致性怎么样,您担心这个吗?例如,线程 A 添加一个事物,线程 B 删除它,然后线程 A 尝试表现得好像该事物仍在集合中一样;你关心?这是并发问题的一部分。

现在,如果您想要的是一个列表,并且您将一直添加和删除节点(不一定是在末尾),那么链表就非常有用。但是,如果您想在集合中搜索特定项目,并且您通常不会同时关心所有项目,那么链接列表就很糟糕了。毕竟,也许您想要一个映射 - ConcurrentHashMap,其中键是事物的 ID,值是事物。每次你搜索一个东西时,你都必须遍历该列表直到找到它,这最终会成为一个 O(N) 问题,对吧,当你遍历该列表时,你会面临并发修改(也许你需要一个 CopyOnWriteArrayList,如果你有 RAM 需要消耗的话)。

我同意其他评论者的观点,即这个问题可能太宽泛,无法得到可靠的是/否答案。有许多不同的方法可以最小化同步和并发访问的成本,但它们都是由系统目标驱动的。一种方法可能对一个系统来说很好,但对另一个系统来说却很糟糕。

我建议做一些简单且可行的事情,并对其进行分析或以其他方式根据您想要的结果来衡量其性能。这可以让您了解真正需要优化的地方。

关于java - ConcurrentLinkedDeque的正确使用,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/51796060/

相关文章:

java - 在java中使用SevenZip.openArchive方法后无法删除文件

java - 如何按频率对单词进行排序

java - 升级到 Java 1.5 及更高版本有哪些危险?

java - JMX短类型参数

java - AWS 无服务器请求 - JSON body/httpMethod 始终为 null

java - 如何使用 uniobject for java 连接到 Unix 上的 UNIDATA

java - mac os x 上的 eclipse JNI_CreateJavaVM 错误

java - 在 Java 中继承泛型接口(interface)

java - 如何在Java中每小时创建日志文件

java - 我的代码不能正常工作? IF 语句多个类