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;
}
}
}
我需要一些关于以下多线程场景的建议。我有一个 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;
}
}
}