У меня есть центральный кеш данных, который обновляется несколькими потоками, выполняющими запросы к базе данных 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, restarting.", identifier);
MyThreadManager.getInstance().startThread(identifier);
try {
Thread.sleep(1000L);
} catch (Exception e) {
LOG.error(e.getMessage());
}
}
Большая проблема, с которой я столкнулся в этой реализации, заключается в том, что она может негативно повлиять на любые другие потоки, пытающиеся получить информацию.
Вопрос. Как реализовать поточно-неблокируемый способ «ожидания» обновления кэша в случае перезапуска потока без влияния на другие потоки, использующие тот же кеш данных.