Использовать элементы из ConcurrentHashMap
Я использую ConcurrentHashMap для буферизации сообщений для веб-сокета.
Каждые 200 мс буфер отправляется в одной строке JSON. после этого я хочу удалить запись с карты.
Я думаю, это небезопасно, потому что во время foreach в буфер могут приходить новые сообщения.
String sendString;
for(String msg : buffer.values()){
sendString += msg;
}
ws.send(sendString);
buffer.clear();
Как я могу безопасно удалить элементы?
4 ответа
Вам необходимо проверить ключ и значение.
StringBuilder sendString = new StringBuilder();
for (Map.Entry<String, String> entry : buffer.entrySet()) {
sendString.append(entry.getValue());
buffer.remove(entry.getKey(), entry.getValue()); // only remove a matching value
}
Map#remove()
возвращает значение, которое существует в карте до удаления. В ConcurrentHashMap
это выполняется атомарно, так что вы можете безопасно использовать результат:
StringBuilder sendString = new StringBuilder();
for (String key : buffer.keySet()) {
String s = buffer.remove(key);
if (s != null)
sendString.append(s);
}
Используйте итератор явно:
StringBuilder result = new StringBuilder();
for (Iterator<String> it = buffer.values().iterator(); it.hasNext(); ) {
result.append(it.next());
it.remove();
}
Поместите весь блок метода в синхронизированный блок. Никакой другой поток не может писать на карту во время выполнения этого кода.
synchronized(buffer){
String sendString;
for(String msg : buffer.values()){
sendString += msg;
}
ws.send(sendString);
buffer.clear();
}
synchronized(buffer){
buffer.put(key, msg);
}