Я столкнулся с этой проблемой: у меня много потоков (1024), которые обращаются к одной большой коллекции - Vector. Вопрос: можно ли что-то с этим сделать, что позволило бы мне выполнять с ним одновременные действия без необходимости все синхронизировать (поскольку это требует времени)? Я имею в виду, что работает что-то вроде базы данных Mysql, вам не нужно беспокоиться о синхронизации и проблемах с потокобезопасностью. Есть ли аналогичная коллекция в Java? Спасибо
Java: большая коллекция и параллельные потоки
Ответы (5)
Vector — это очень старый класс Java, предшествующий API коллекций. Он синхронизируется при каждой операции, поэтому вам не повезет, если вы попытаетесь его ускорить. Вам следует подумать о переработке своего кода, чтобы использовать что-то вроде ConcurrentHashMap или LinkedBlockingQueue, которые очень оптимизированы для одновременного доступа.
В противном случае вы упоминаете, что хотели бы производительность и семантику доступа, аналогичную базе данных - почему бы не использовать выделенную базу данных или очередь сообщений? Скорее всего, они реализуют его лучше, чем вы когда-либо, и вам придется писать меньше кода!
[править] Учитывая ваш комментарий:
all what thread does is adding elements to vector
(only if num of elements in vector = 0) &
removing elements from vector. (if vector size > 0)
это звучит очень похоже на то, что вы должны использовать что-то гораздо больше похожее на очередь, чем на список! Ограниченная очередь размером 1 даст вам эту семантику, хотя я бы спросил, почему вы не можете добавлять элементы, если там уже что-то есть. Когда у вас тысячи потоков, это кажется очень неэффективным дизайном.
Ну, во-первых, этот дизайн звучит неправильно. Похоже, вам нужно подумать об использовании правильной базы данных, а не простой структуры данных, даже если это означает просто использование чего-то вроде экземпляра в памяти HysonicDB.
Однако, если вы настаиваете на этом, то java.util.concurrent имеется ряд высококонкурентных неблокирующих структур данных. Один из них может подойти для ваших целей (например, ConcurrentHashMap, если вы можете использовать Map
вместо List
)
Похоже, вы реализуете шаблон производителя-потребителя, вам следует поискать в Google «производитель-потребитель java» или посмотреть интерфейс BlockingQueue
Я согласен со скаффманом по поводу просмотра java.util.concurrent.
ConcurrentHashMap очень масштабируем. Однако вызов size() возвращает только приблизительное значение. Так, например. ваше приложение будет время от времени добавлять к нему элементы, даже если !(количество элементов в векторе = 0).
Если вы хотите строго соблюдать заданное вами условие, нет другого способа, кроме синхронизации.
Вместо того, чтобы иметь тонны переключений контекста, я думаю, вы могли бы позволить своим пользователям размещать вызываемый объект в очереди и иметь только один поток, занимающийся мутацией. Это устранит необходимость синхронизации в коллекции. Пользовательские потоки могут ожидать Future.get().
Просто идея.
Если вы не хотите изменять структуру данных и выполняете только нечастую запись, вы также можете использовать один или несколько ReentrantReadWriteLock для синхронизации доступа. Тогда многие потоки могут читать одновременно, но когда поток хочет записать, все операции чтения блокируются до тех пор, пока не будет выполнена запись.
Но вы должны проверить, подходит ли используемая структура данных для задачи, или другой из многих классов java.util или java.util.concurrent более подходит. Между прочим, java.util.Vector синхронизирован.