基于平面文件的Java内存读/写缓存

时间:2015-05-05 10:28:52

标签: java multithreading caching guava

我有一个平面文件,其中包含设备标识符列表。当我的基于Java / tomcat的应用程序从特定设备接收请求时,它根据文件中设备标识符的存在来决定业务逻辑(即使设备存在,设备标识符也可能不存在于文件中)。

还有用例
  1. 需要将新标识符添加到文件
  2. 可以从文件中删除标识符。
  3. 为了使(多线程)应用程序更快,而不是每次读/写操作直接访问文件,我需要将内容存储在内存中。

    以下是要求(摘要):

    1. 在应用程序启动期间读取内存(缓存)中文件的内容。

    2. 以多线程方式从缓存中读取内容。如果内容不在缓存中,则不应该在文件中,反之亦然(单点)。

    3. 当有新设备标识时,需要更新缓存和文件。

    4. 当需要删除设备标识时,需要更新缓存和文件。

    5. 该应用程序以Java格式运行。

    6. 有哪些选择?我最初想过使用gauva缓存。但是,我不确定它是否支持将其内容写回源文件。 即使是简单的属性文件(java.util.properties)也应该这样做。但是,不确定这是否适合高度多线程的环境。

      感谢您的建议。

2 个答案:

答案 0 :(得分:4)

与大多数缓存一样,Guava的主要用于以直读方式使用。目的是更新权威数据源,然后使缓存失效。缓存不支持直写或后写,并且在顶部添加这些功能可能会导致微妙的竞争条件。

Java 8重写Caffeine支持通过ConcurrentHashMap's原子计算方法添加该功能。直写使用更新数据源的compute,如果成功,则将值存储在缓存中。后写使用compute方法,该方法异步更新数据源并乐观地将值存储在缓存中。在这两种情况下,如果条目在计算期间存在,则读取是非阻塞的,并且在更新完成之前接收旧值。

对于内存缓存的常见用法,直写和后写都不是很好的方法。在适当的时候,他们需要更周到的关怀和定制,因此提供通用支持被认为会导致开发人员误入歧途,并提供很少的好处。重写提供了使功能成为可能的机会,而无需直接推广。

答案 1 :(得分:1)

作为使用HashSet作为扩展点的起点。

 class DeviceCache extends HashSet<Device> {

  boolean add(Device d) {
    boolean rv = super.add(d);

    if (!rv) {
      ... Add the device to the file.
    }

    return rv;
  }

  remove(Device d) {
    boolean rv = super.remove(d);

    if (rv) {
    ... Remove the device from the file
    }

    return fv;
  }
}

远未完成。有什么想法吗?