у нас есть многопоточное приложение с классическим подходом производителя / потребителя, которое использует очередь ConcurrentHashmap.
Потребитель запускает поток, внутри которого есть бесконечный цикл с другим вложенным циклом на параллельной хэш-карте, которая считывает и удаляет каждый обработанный элемент.
Я спрашиваю себя, является ли этот код безопасным / эффективным в отношении итерации «для» на карте и «удаления» для каждого элемента.
Запуск кода кажется правильным ...
new Thread(t.getContextName()+"-RespMsgThread") {
public void run() {
try {
do {
for (Entry<Integer, AbstractMessage> nodeEntry : t.getHtForResponse().entrySet())
{
--> Doing some stuff with the node Entry
// remove the node from the queue
t.getHtForResponse().remove(nodeEntry.getKey());
}
yield();
}
while (!t.isStopControllerRun());
} catch (InterruptedException ex) {
Context.getInstance().getLogger().info("ERROR: " + ExceptionUtils.getStackTrace(ex));
}
}
}.start();
Всего 2 ответа
Да, это совершенно безопасное / эффективное отношение к итерациям. Есть одна загвоздка, потому что итератор для ConcurrentHashMap слабо согласован, вы можете удалить значение для ключа, который вы не обработали (делая некоторые вещи с помощью Entry узла в вашем случае).
Таким образом, вы можете рассмотреть возможность вызова метода
remove(Object key, Object value)
removes the entry for a key only if currently mapped to a given value.
Вместо простого метода удаления (ключ объекта)
Когда на карте нет предметов, которые вы только уступаете, возможно, вы можете спать. В качестве альтернативы сна вы можете использовать что-то вроде BlockingQueue . Используя метод take () в BlockingQueue, вы получите элемент, как только он будет вставлен. Вы также можете использовать метод poll (timeout, timeunit) для проверки, остановлен ли поток.