1

Поддержка есть несколько потоков, выполняющих задачи запроса, которые каждый из них вернет list в результате, какая структура данных будет быстрее для слияния результатов?Слияние списка одновременно - что лучше, CopyOnWriteArrayList или ConcurrentLinkedQueue?

ConcurrentLinkedQueue

Неограниченная поточно-очереди на основе связанных узлов. Эта очередь заказывает элементы FIFO (first-in-first-out). Глава очереди - это тот элемент, который был в очереди самым длинным. Хвост очереди - это тот элемент, который был в очереди в кратчайшее время. Новые элементы вставляются в хвост очереди, а операции поиска очереди получают элементы в начале очереди. ConcurrentLinkedQueue является подходящим выбором, когда многие потоки будут предоставлять доступ к общей коллекции. Как и большинство других параллельных реализаций коллекции, этот класс не позволяет использовать нулевые элементы. Эта реализация использует эффективный «безжизненный» алгоритм, основанный на одном из описанных в простых, быстрых и практических алгоритмах без очереди и блокирования параллельных очередей Магедом М. Майклом и Майклом Л. Скоттом.

CopyOnWriteArrayList

Как название предлагает CopyOnWriteArrayList создает копию основного ArrayList с каждой операцией мутации, например, добавить или установить. Обычно CopyOnWriteArrayList очень дорог, потому что требует дорогостоящей копии массива с каждой операцией записи, но очень эффективен, если у вас есть список, в котором итерация превышает количество мутаций, например. вам в основном нужно перебирать ArrayList и не изменять его слишком часто.

+1

Что вы думаете? – Kayaman

+2

Весь подход нескольких потоков, объединяющих их вывод в общую структуру данных, является ошибочным. Оптимальные системы никогда этого не делают; вместо этого у них есть нисходящий поток, который принимает частичные результаты от нескольких потоков в параллельной очереди и затем объединяется в одну пакетную операцию. –

+0

@MarkoTopolnik это исключало бы сценарий, в котором у вас долгоживущие потоки, и вы хотите проверять результаты по мере их создания, вместо того, чтобы ждать окончательной пакетной операции. – tucuxi

ответ

3

ConcurrentLinkedQueue позволяет вам писать, долго ждать, очень эффективно. Это будет медленнее, чем CopyOnWriteArrayList для чтения, но не намного. Для этого потребуется немного больше места (меньше указателей).

CopyOnWriteArrayList немного компактнее и обеспечивает более быстрое считывание, но требует больших копий при записи, что дорого.

Слияние (при условии, что вы не заботитесь о заказе или дублировании) является операцией только для записи, поэтому вы должны выбрать ConcurrentLinkedQueue.

+0

Да, я не забочусь о заказе или дублировании. –

+0

Я только что прочитал исходный код 'CopyOnWriteArrayList'. И да, это требует полных копий при записи. Но когда мы копируем список, мы будем использовать метод 'addAll()', который будет использовать API 'System.arraycopy() для выполнения пакетной копии в массиве, это очень эффективно. –

2

Если ваши задачи запроса действительно возвращают список, то он будет намного быстрее объединять результаты в одном потоке с использованием обычного ArrayList.

+0

Я понял, что потоки пытались одновременно заполнить список «результатов» – tucuxi

+0

@tucuxi Каждая задача вернет «список» в результате. –