Многопоточный потребитель Java со стратегией ConcurrentHashmap

у нас есть многопоточное приложение с классическим подходом производителя / потребителя, которое использует очередь 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) для проверки, остановлен ли поток.


Есть идеи?

10000