1. Что такое блокирующая очередь?
Очередь - это структура данных, которая имеет две основные операции: добавление элемента в конце очереди и удаление элемента из головы очереди. Разница между блокирующими командами и обычными очередями заключается в том, что обычные очереди не будут блокировать текущий поток. При столкновении с аналогичными моделями потребителей, необходимо реализовать дополнительные стратегии синхронизации и межпоточные стратегии пробуждения. Использование блокировки очереди заблокирует текущий поток. Когда очередь пуст, операция получения элементов из очереди будет заблокирована. Когда очередь заполнена, операция добавления элементов в очередь также будет заблокирована.
2. Основная очередь блокировки и ее методы
Пакет java.util.concurrent предоставляет несколько основных очередей блокировки, главным образом следующим образом:
1) ArrayBlockingQueue: очередь блокировки на основе реализации массива. При создании объекта ArrayBlockingQueue должна быть указана его емкость. Это также может быть указано для политик доступа. По умолчанию это несправедливо, то есть не гарантирует, что поток с самым длинным временем ожидания сможет сначала получить доступ к очереди.
2) LinkedBlockingQueue: очередь блокировки на основе связанного списка. Если размер емты не указан при создании объекта LinkedBlockingQueue, размер по умолчанию ISEGER.MAX_VALUE.
3) Вышеуказанные две очередь-в первую очередь в очереди, но приоритетная блокировка-нет. Он сортирует элементы в соответствии с приоритетом элементов и декуэ в приоритетном порядке. Каждый элемент Dequeue является наивысшим приоритетным элементом. Обратите внимание, что эта блокирующая очередь представляет собой неограниченную очередь блокировки, то есть нет верхнего предела на емкость (вы можете знать через исходный код, что у него нет сигнального флага, полного контейнера). Первые два типа - ограниченные очереди.
4) DolectQueue: на основе приоритетной quiewue, очереди блокировки задержки. Элемент в задержке может получить элемент из очереди только после достижения указанного времени задержки. DolectQueue также является неограниченной очередью, поэтому операция (производитель) вставки данных в очередь никогда не будет заблокирована, и будет заблокирована только операция (потребитель) получения данных.
Очерки блокировки включают в себя большинство методов в неблокирующих очередях и предоставляют несколько других очень полезных методов:
Метод POT используется для хранения элементов к хвосту очереди, и если очередь полна, подождите;
Метод принятия используется для получения элементов из очереди, и если очередь пуста, подождите;
Метод предложения используется для хранения элементов на хвосте очереди. Если очередь заполнена, она будет ждать определенного времени. Когда период времени достигнут, если вставка не была успешной, он вернет ложь; В противном случае это вернет правдоподобно;
Метод опроса используется для получения элементов из первой очереди. Если очередь пуст, она будет ждать определенного времени. Когда период времени достигнут, если он будет извлечен, он вернется на ноль; В противном случае он вернет полученный элемент;
Вот код:
Import java.util.concurrent.arrayblockqueueue;/** * @author Автор: xu jiane-mail: [email protected] * @version Создано: 20 марта 2016 г. в 12:52:53. * java.util.concurrent.blockqueue <string> blockqueue = new Arrayblockingqueue <> (5); for (int i = 0; i <10; i ++) {// добавить указанный элемент в эту очередь blockingqueue.put ("добавить элемент"+i); System.out.println («Добавленный элемент в очередь блокировки:» + i); } System.out.println («Программа заканчивается на этот раз и выходит из-за ----»); }}
Когда количество очередей блокировки лимит составляет 5, после добавления 5 элементов процесс будет заблокирован вне очереди и ожидание, а в настоящее время программа не завершается.
Когда очередь заполнена, мы удаляем элемент заголовка, и мы можем продолжать добавлять элементы в очередь блокировки. Код заключается в следующем:
открытый класс Blockqueue {public static void main (string [] args) бросает прерывание {java.util.concurrent.blockqueue <string> blockquequeue = new Arrayblockingqueue <> (5); for (int i = 0; i <10; i ++) {// добавить указанный элемент в эту очередь blockingqueue.put ("добавить элемент"+i); System.out.println («Добавленный элемент в очередь блокировки:» + i); if (i> = 4) System.out.println ("Удалить элемент заголовка" +blockqueque.take ()); } System.out.println («Программа заканчивается на этот раз и выходит из-за ----»); }Результаты выполнения следующие:
3.
Во -первых, давайте посмотрим на переменные члена класса Arrayblockingqueue:
Общедоступный класс ArrayBlockqueUe / ** Подписк элемента команды*/ int takeDindex; / ** Индекс команды хвоста хвоста*/ int putindex; / ** Общее количество элементов очереди*/ int count; / ** reentrantlock*/ final Reentrantlock Lock; / ** Условие ждать notempty*/ частное окончательное условие notempty; / ** Заметно условие ожидания*/ частное окончательное условие заметно; /** * Общее состояние для активных итераторов в настоящее время или NULL, если * известно, что их нет. Позволяет операциям очереди обновлять * итераторное состояние. */ Transiet Itrs itrs = null;
Как вы можете видеть, ArrayblockingQueue для хранения элементов на самом деле является массивом.
Давайте посмотрим на реализацию двух важных методов Arrayblockingqueue, put () и Take ():
public void put (e e) бросает прерванные эктриэкцепции {// Сначала проверьте, является ли E пустая ecectnull (e); // Приобретение блокировки Final Reentrantlock Lock = this.lock; lock.lockintertible (); Попробуйте {// Когда очередь заполнена, введите условие и подождите, пока (count == items.length) natfull.await (); // очередь не выполнена, выполните операцию очереди Enqueue (e); } наконец {// Отпустите блокировку lock.unlock (); }} Давайте посмотрим на конкретную операцию соединения:
private void enqueue (e x) {final object [] items = this.items; // элементы Enmination [putindex] = x; if (++ putindex == items.length) putindex = 0; // общее количество очередей +1 count ++; // Выберите поток случайным образом в наборе ожидания условия Notempty, чтобы разблокировать его состояние блокировки notempty.signal (); } Вот исходный код метода Take ():
public e take () бросает прерванные эктриэкцепции {// Приобретение блокировки окончательного reentrantlock lock = this.lock; lock.lockintertible (); try {// очередь пуста, while (count == 0) // Поток присоединяется к установке ожидания Notempty NoteMpty.await (); // не пустые, выйдите из очереди return dequeue (); } наконец {// Отпустите блокировку lock.unlock (); }} 4. Применение блокирующих очередей: внедрение модели потребительского продюсера
/** * @author Автор: xu jiane-mail: [email protected] * @version Создано время: 20 марта 2016 г. в 14:21:55 * Класс Описание: Режим потребительского продюсера, реализованный путем блокирования очереди */public Class Test {private keeuesize = 10; Private ArrayBlockingqueue <Integer> queue = new Arrayblockingqueue <Integer> (queuesize); public static void main (string [] args) {test test = new Test (); Производитель производитель = test.new Producer (); Потребительский потребитель = test.new Consumer (); Produce.Start (); Consumer.Start (); } class Consumer Extends Thread {@Override public void run () {enurning (); } private void потребление () {while (true) {try {queue.take (); System.out.println («Возьмите элемент из очереди, а очередь остается" + queue.size () + "элементы"); } catch (прерванное искусство e) {e.printstacktrace (); }}}} Производитель класса Extends Thread {@Override public void run () {upport (); } private void irus () {while (true) {try {queue.put (1); System.out.println («Вставьте элемент в очередь, оставшееся пространство в очередь:»+ (queuesize - queue.size ())); } catch (прерванное искусство e) {e.printstacktrace (); }}}}}}
Выше приведено в этой статье, я надеюсь, что это будет полезно для каждого обучения.