我有一个中央数据缓存,该缓存由许多在SQL数据库上运行查询的线程更新。还有一种机制可以检查何时最后一次检索到数据高速缓存中的每个特定项(Mydata
),并在达到某个时间阈值时(即,如果尚未检索到数据)关闭相应的线程。最后30分钟)。可以使用这种机制来尝试减少对数据库的需求并最大程度地减少长时间运行的查询。
还有许多线程从缓存中获取数据,因此,问题在于,即使不再更新特定项(Mydata
),线程也可能会在某个时候请求它。发生这种情况时,将检查相关线程是否正在运行,如果没有运行,则重新启动,如下所示...
private static HashMap<String,MyData> dataMap = new HashMap<>(10);
public static MyData getMyData(String identifier) {
if(!MyThreadManager.getInstance().isRunning(identifier)) {
LOG.info("Thread with identifier={} possibly stopped,restarting.",identifier);
MyThreadManager.getInstance().startThread(identifier);
}
MyData myData= null;
if(dataMap.containsKey(identifier)) {
myData= dataMap.get(identifier);
} else {
LOG.debug("No data found in dataMap for identifier={},thread possibly terminated. Restarting.",identifier);
}
return myData;
}
...该机制本身运行良好,但是冒着这样的风险,即在运行dataMap.get(identifier)
时,它可能仍只包含myData
的“过时”版本(因为重新启动的线程)可能仍在处理中)。但是,我想保证返回的数据已经更新。为此,我可以在重新启动线程一秒钟后添加一个睡眠计时器,这应该足以让线程在运行dataMap
之前更新dataMap.get(identifier)
中的数据。
if(!MyThreadManager.getInstance().isRunning(identifier)) {
LOG.info("Thread with identifier={} possibly stopped,identifier);
MyThreadManager.getInstance().startThread(identifier);
try {
Thread.sleep(1000L);
} catch (Exception e) {
LOG.error(e.getMessage());
}
}
此实现的最大问题是,它可能会对尝试检索信息的任何其他线程产生负面影响。
问题:在线程重新启动的情况下,我如何实现线程安全/非锁定方式来“等待”更新缓存,同时又不影响使用同一数据缓存的其他线程。