У меня есть ConcurrentHashMap, который иногда ведет себя странно.
Когда мое приложение запускается впервые, я читаю каталог из файловой системы и загружаю содержимое каждого файла в ConcurrentHashMap, используя имя файла в качестве ключа. Некоторые файлы могут быть пустыми, и в этом случае я устанавливаю значение «пусто».
Как только все файлы будут загружены, пул рабочих потоков будет ожидать внешних запросов. Когда приходит запрос, я вызываю функцию getData(), где проверяю, содержит ли ConcurrentHashMap ключ. Если ключ существует, я получаю значение и проверяю, является ли значение «пустым». Если value.contains("пусто"), я возвращаю "файл не найден". В противном случае возвращается содержимое файла. Когда ключ не существует, я пытаюсь загрузить файл из файловой системы.
private String getData(String name) {
String reply = null;
if (map.containsKey(name)) {
reply = map.get(name);
} else {
reply = getDataFromFileSystem(name);
}
if (reply != null && !reply.contains("empty")) {
return reply;
}
return "file not found";
}
Иногда ConcurrentHashMap будет возвращать содержимое непустого файла (т. е. value.contains("empty") == false
), однако строка:
if (reply != null && !reply.contains("empty"))
возвращает ЛОЖЬ. Я разбил оператор IF на две части: if (reply != null)
и if (!reply.contains("empty"))
. Первая часть оператора ЕСЛИ возвращает ИСТИНА. Вторая часть возвращает ЛОЖЬ. Поэтому я решил распечатать переменную «ответ», чтобы определить, действительно ли содержимое строки содержит «пусто». Это было НЕ так, т.е. содержимое не содержало строки «пусто». Кроме того, я добавил строку
int indexOf = reply.indexOf("empty");
Поскольку ответ переменной не содержал строки «пусто», когда я ее распечатывал, я ожидал, что indexOf
вернет -1. Но функция вернула значение, приблизительно равное длине строки, то есть if reply.length == 15100
, тогда reply.indexOf("empty")
возвращало 15099.
Я сталкиваюсь с этой проблемой еженедельно, примерно 2-3 раза в неделю. Этот процесс перезапускается ежедневно, поэтому ConcurrentHashMap регулярно создается заново.
Кто-нибудь видел такое поведение при использовании Java ConcurrentHashMap?
ИЗМЕНИТЬ
private String getDataFromFileSystem(String name) {
String contents = "empty";
try {
File folder = new File(dir);
File[] fileList = folder.listFiles();
for (int i = 0; i < fileList.length; i++) {
if (fileList[i].isFile() && fileList[i].getName().contains(name)) {
String fileName = fileList[i].getAbsolutePath();
FileReader fr = null;
BufferedReader br = null;
try {
fr = new FileReader(fileName);
br = new BufferedReader(fr);
String sCurrentLine;
while ((sCurrentLine = br.readLine()) != null) {
contents += sCurrentLine.trim();
}
if (contents.equals("")) {
contents = "empty";
}
return contents;
} catch (Exception e) {
e.printStackTrace();
if (contents.equals("")) {
contents = "empty";
}
return contents;
} finally {
if (fr != null) {
try {
fr.close();
} catch (Exception e) {
e.printStackTrace();
}
}
if (br != null) {
try {
br.close();
} catch (Exception e) {
e.printStackTrace();
}
}
if (map.containsKey(name)) {
map.remove(name);
}
map.put(name, contents);
}
}
}
} catch (Exception e) {
e.printStackTrace();
if (contents.equals("")) {
contents = "empty";
}
return contents;
}
return contents;
}
foo.indexOf("empty")
когда-нибудь вернетfoo.length() - 1
для непустой строки. Это означало бы, чтоString.indexOf
очень сломан. Я не верю, чтоConcurrentHashMap
илиString
сломаны - я сильно подозреваю, что ваш код где-то сломан. - person Jon Skeet   schedule 09.07.2012getDataFromFileSystem(name);
? - person assylias   schedule 09.07.2012getDataFromFileSystem
есть несколько проверок дляcontents.equals("")
, но это никогда не может быть правдой, потому чтоString contents = "empty";
. - person Miserable Variable   schedule 10.07.2012