【问题标题】:Retain Latest version of object [closed]保留对象的最新版本[关闭]
【发布时间】:2019-08-30 04:41:43
【问题描述】:

我需要以多线程方式从源中读取数据。源可以包含各种资源的消息。为了确保快速阅读,我正在使用多个线程进行阅读。同一资源可能有多条消息,在这种情况下,我只想保留最新消息。

class Message {

    String id;
    String data;
    long timeStamp
}

我正在想办法解决这个问题。鉴于我将以多线程方式阅读,不确定哪种数据结构最适合?以 id 为键的 ConcurrentHashMap?在这种情况下,我需要检查密钥是否存在。如果是,则比较消息并在必要时进行更新。如果在比较两个版本时可能会发生这种情况,则第三版消息会到达并更新,因为当时我不会采取写锁定。在检查和更新周围添加同步块是唯一的方法吗?有什么有效的建议吗?

【问题讨论】:

  • 到目前为止你有没有尝试过?请分享您的努力,如果需要,人们可以帮助您纠正
  • 分发消息的来源。你如何访问它?如果资源有多个消息,是否会返回所有消息?
  • @Kris:不是在找代码,只是一种方法。
  • @user7:是的。我会得到资源的所有消息。一种选择是首先获取所有资源的所有消息,然后开始清除每个资源的陈旧消息。但是我发现这有点低效。
  • 要求我们推荐或查找书籍、工具、软件库、教程或其他场外资源的问题对于 Stack Overflow 来说是无关紧要的,因为它们往往会吸引固执己见的答案和垃圾邮件。相反,请描述问题以及迄今为止为解决该问题所做的工作

标签: java multithreading performance concurrency jvm


【解决方案1】:

如果只是读取,可以在变量前使用volatile关键字来指示JVM,它可以被多个线程同时访问。这样您就不会受到过时数据的影响。

另一方面,如果要同时修改变量,则需要锁定(使用synchronized 块或非内在锁定)。 volatile 提供可见性、锁定-可见性原子性。

P.S.:取自this book。

【讨论】:

    【解决方案2】:

    我需要以多线程方式从源中读取数据。

    如果您从单一来源读取数据并且处理时间不密集,那么您可能不会从多线程中获得任何收益。相反,它会损害性能。 “多线程”意味着“让事情变得更快”,这是一个(非常)普遍的信念。

    以 id 为键的 ConcurrentHashMap?在这种情况下,我需要检查 如果密钥存在。如果是,则比较消息并更新 if 必要的。如果在比较两个版本时可能会发生这种情况,第三个 消息的版本到达并更新,因为我不会采取 当时写锁。

    使用ConcurrentHashMap.compute()。它锁定密钥(以及地图的一部分)以防止任何无序更新。类似于以下内容。

    Message newMsg = getFromSomewhere();
    map.compute(id, (k, oldVal) -> {
        if(oldVal == null) // First value for this key
            return newMsg;
    
        // Compare the timestamp and return the newer one as the new value in the map
        if(oldVal.getTimestamp() > newMsg.getTimestamp())
            return oldVal;
    
        return newMsg;
    });
    

    为了获得额外的(CPU 限制)性能,您可以尝试使用 ConcurrentHashMap(int initialCapacity, float loadFactor, int concurrencyLevel) 构造函数微调地图。

    【讨论】:

      猜你喜欢
      • 2022-10-15
      • 2020-05-06
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2014-10-31
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多