Ehcache多线程场景

Ehcache multithreading scenario

我需要一些关于以下多线程场景的建议。我有一个 xml 文件,其中包含 Web 应用程序的一些配置数据。当用户访问该网站时,根据用户访问的 url ,将读取 XML 文件中的数据以找出该用户请求附带的一些属性。为了提高从 xml 文件读取的性能,我使用了 Ehcache。我在缓存中缓存来自 xml 的请求和相关配置。

所以,现在我面临的问题是。如果有人开始更新 xml 文件,我需要停止从缓存读取直到写入完成,一旦 xml 文件更新操作完成,我想清除缓存。然后缓存将再次重建。对于第二部分,我正在努力研究如何实现多线程来实现这一点。文件更新可以通过两种方式完成,一种是用户直接使用记事本++或其他工具编辑xml文件。另一种方法是使用相同的网络应用程序。

您可以使用从共享 BlockingQueue 读取的工作线程池刷新缓存;当用户完成他们的编辑时,您将向队列发送一条消息,其中包含有关需要更新的 kv 对的信息。

public class RefreshRequest<K> {
    public final K key;
    public RefreshRequest(K key) { this.key = key; }
}

public final BlockingQueue<RefreshRequest<?>> requestQueue = new ArrayBlockingQueue<>(200);
public final int concurrency = 4;
public final ExecutorService executor = Executors.newFixedThreadPool(4);

for(int i = 0; i < concurrency; i++) {
    executor.execute(new Runnable() {
        public void run() {
            try {
                while(true) {
                    RefreshRequest<?> request = requestQueue.take();
                    // refresh key
                }
            } catch(InterruptedException e) {
                return; // maybe log the exception as well
            }
        }
    };
}

工作人员将消费刷新缓存键的请求;您需要 put 队列中的新请求,这些请求来自完成对 xml 文件的更改的代码。要终止工作人员调用 executor.shutdownNow(),它将使用 InterruptedException

跳出 while(true) 循环

至于当有人开始写入 xml 时如何停止从缓存中读取,您可以通过 "optimistic" 读取来实现。为每个 xml 文件分配一个版本号,并在写入文件时递增此版本。开始读取时,将文件的版本存储在局部变量中。读取完成后,将本地版本与文件的当前版本进行比较 - 如果它们匹配,则 return 读取值,如果它们不匹配,则重复读取,包括将局部变量更新为当前文件版本.如果需要,您可以使用 "invalid" 版本(例如 "valid" 版本从 0 开始并在每次写入时递增,而 "invalid" 版本为负 1)- 如果 reader 读取文件是 "invalid" 然后它暂停例如5 秒,然后重试。所以一种算法可能是

public Object read(K key) {
    while(true) {
        int version = versionCache.get(key);
        if(version == -1) Thread.sleep(5000);
        else {
            Object returnVal = cache.get(key);
            if(version == versionCache.get(key)) 
                return returnVal;
        }
    }
}