Java.util.ConcurrentLinkedQueue

Я хочу использовать java.util.ConcurrentLinkedQueue как непростую очередь для сервлета. Здесь размещен фрагмент из javadoc для класса.

Неограниченная поточно-безопасная очередь на основе связанных узлов. ConcurrentLinkedQueue является подходящим выбором, когда многие потоки будут предоставлять доступ к общей коллекции. Эта очередь не допускает нулевые элементы.

Теперь представьте, что у меня есть 1000 одновременных запросов на сервлет, и каждый поток должен будет вставить объект в ConcurrentLinkedQueue. Из описания следует сделать вывод, что у него не будет проблем с обработкой нагрузки? Гарантия, которая мне понадобится, заключается в следующем:

  • Я автоматически получаю потокобезопасную гарантию без необходимости выполнять собственную синхронизацию.
  • Я не потеряю никаких запросов, если загрузка трафика превышает 1000 одновременных запросов.

Спасибо

Ответ 1

В основном вы задаете три разных вопроса (два из них явно и одно неявно). Вот они, с моими ответами:

1. Нужно ли выполнять собственную синхронизацию, если я использую java.util.ConcurrentLinkedQueue?

Атомные операции с параллельными коллекциями синхронизированы для вас. Другими словами, каждый индивидуальный вызов в очередь гарантируется потокобезопасностью без каких-либо действий с вашей стороны. Что такое не гарантированное потокобезопасное - это любые операции, которые вы выполняете в неатомной коллекции.

Например, это потокобезопасное без каких-либо действий с вашей стороны:

queue.add(obj);

или

queue.poll(obj);

Тем не менее; неатомные вызовы в очередь не являются поточно-безопасными. Например, следующие операции не автоматически потокобезопасны:

if(!queue.isEmpty()) {
   queue.poll(obj);
}

Этот последний не является потокобезопасным, так как очень возможно, что между вызовом isEmpty и вызовом времени, другие потоки будут добавлять или удалять элементы из очереди. Понятно, как это сделать:

synchronized(queue) {
    if(!queue.isEmpty()) {
       queue.poll(obj);
    }
}

Снова... атомные вызовы в очередь автоматически потокобезопасны. Неатомные вызовы не являются.

2. Я уверен, что не должен терять звонки на java.util.ConcurrentLinkedQueue, если есть 1000 одновременных запросов?

Поскольку это неограниченная реализация, вам гарантировано, что независимо от количества одновременных запросов очередь не потеряет эти запросы (из-за очереди concurrency... у вас может закончиться нехватка памяти или некоторых таких... но сама реализация очереди не будет вашим ограничивающим фактором.) В веб-приложении есть другие возможности "потерять" запросы, но синхронизация (или их отсутствие) очереди не будет вашей причиной.

3. Будет ли java.util.ConcurrentLinkedQueue работать достаточно хорошо?

Обычно мы говорим о "правильности", когда говорим о concurrency. Я имею в виду, что параллельные классы гарантируют, что они потокобезопасны (или надежны против блокировки, голодания и т.д.). Когда мы говорим об этом, мы не делаем никаких гарантий относительно производительности (как быстро звонки в коллекцию ) - мы только гарантируем, что они "правильны".

Тем не менее; ConcurrentLinkedQueue - это "безжизненная" реализация, поэтому это, вероятно, так же хорошо, как вы можете получить. Единственный способ гарантировать загрузку сервлета (включая использование параллельных классов) - проверить его при загрузке.

Ответ 2

Помните, что очередь только потокобезопасна для вызовов одного члена. Не пишите такой код и ожидайте его работы:

if (queue.Count!=0)
    queue.Dequeue().DoSomething();

В промежутке между этими двумя операциями другой поток может удалить последний элемент. Я не интимный с коллекциями Java, но я думаю, что Dequeue в таком случае вернет null, предоставив вам исключение.

Ответ 3

  • Поскольку очередь является потокобезопасной, вам не нужно выполнять какие-либо синхронизации для обеспечения безопасности потоков. Тем не менее, вы должны убедиться, что все потоки имеют равный доступ к очереди, чтобы избежать голодания, ожидание и т.д.

  • Поскольку очередь не ограничена, размер очереди ограничен только объемом доступной памяти.

Ответ 4

Да, для ваших двух вопросов.

Параллельная очередь является потокобезопасной (и эффективна из-за используемого ниже алгоритма без блока). подразумевает, что количество параллельных доступов не должно иметь никакого значения (я еще не слышал о состоянии гонки, который гарантированно не будет выполняться ниже одновременных запросов xyz).

Кроме этого - оптимальная производительность в многопоточных приложениях сложнее. Но использование реальной параллельной коллекции не слишком плохое начало.