В этой статье в основном рассказывается о коллекциях, связанных с параллелизмом. Для обычных коллекций, пожалуйста, обратитесь к [Обзор коллекции Java]
1. Что такое блокировка
Blockingqueue - это блокирующая очередь. Из блокировки слова можно увидеть, что доступ к очереди блокировки может вызвать блокировку в некоторых случаях. Есть два основных заблокированных случая:
1. Когда очередь будет заполнена, она будет включена.
2. Когда очередь пуст, она будет вне очереди.
Поэтому, когда поток пытается стоять в очереди и без того полной очереди, она будет заблокирована, если только другой поток не выполняет операцию очереди; Точно так же, когда поток пытается стоять в очереди пустой очереди, она будет заблокирована, если только другой поток не имеет операции очереди.
В Java интерфейс Blockingueue расположен в пакете java.util.concurrent (предусмотрено в версии Java 5). Из характеристик блокируемой очереди, введенной выше, можно видеть, что блокировка очередь безопасна.
2. Как использовать BlockingQueue
Блокирующие очереди используются в основном в сценариях производителей/потребителей. На следующем изображении показано производство потока и сценарий потребления потока:
Поток, ответственный за производство, постоянно создает новые объекты и вставляет их в очередь блокировки до тех пор, пока не будет достигнут верхний предел этой очереди. После того, как очередь достигнет своего верхнего предела, производственный поток будет заблокирован до тех пор, пока потребляемый нить не потребляет очередь. Точно так же поток, ответственный за потребление, постоянно потребляет объекты из очереди до тех пор, пока очередь не станет пустой. Когда очередь пуст, поток потребления будет заблокирован, если не вставлен новый объект в очередь.
3. Методы в интерфейсе блокировки
Существует четыре набора методов блокировки очередей для выполнения insert , remove и examine соответственно. Когда операции, соответствующие каждому набору методов, не могут быть выполнены немедленно, будут разные реакции. В следующей таблице перечислены эти методы классифицированным образом:
| - | Бросает исключение | Специальное значение | Блоки | Раз |
|---|---|---|---|---|
| Вставлять | добавить (o) | Предложение (O) | положить (o) | Предложение (O, тайм -аут, TimeUnit) |
| Удалять | Удалить (o) | голосование() | брать() | Опрос (Тайм -аут, TimeUnit) |
| Исследовать | элемент() | peek () |
Соответствующие характеристики этих четырех наборов методов:
1. Throwsexception: Если операция не может быть выполнена немедленно, будет брошено исключение.
2. SpecialValue: Если операция не может быть выполнена немедленно, будет возвращено специальное значение, обычно верно или неверно
3. Блоки: если операция не может быть выполнена немедленно, операция будет заблокирована
4. Timesout: Если операция не может быть выполнена немедленно, операция будет заблокирована в указанное время. Если указанное время не выполнено, будет возвращено специальное значение, которое обычно является истинным или ложным.
Следует отметить, что мы не можем вставить null в блокировку, в противном случае будет сообщено NullPointerException .
4. Класс реализации блокировки
Blockingqueue - это всего лишь интерфейс в пакете java.util.concurrent . При использовании его конкретно мы используем его классы реализации. Конечно, эти классы реализации также расположены в пакете java.util.concurrent . В Java 6 классы реализации блокировки в основном следующие:
1. Arrayblockingqueue
2. Dolectqueue
3. LinkedBlockingqueue
4. Приоритетная блокировка
5. Synchronousqueue
Ниже мы представим эти классы реализации отдельно.
4.1 Arrayblockingqueue
ArrayBlockingQueue - это ограниченная очередь блокировки, а его внутренняя реализация - массив. Значение границы означает, что его емкость ограничена, мы должны указать ее размер емкости, когда она инициализирована, и размер емкости не может быть изменен после ее указания.
ArrayBlockingQueue сохраняет данные первым в первую очередь. Недавно вставленным объектом является хвост, а недавно перемещенный объект - это голова. Вот пример инициализации и использования ArrayBlockingQueue:
Queue queue = new Arrayblockingqueue (1024); queue.put ("1"); объект объекта = queue.take ();4.2 DelayQueue
Какие блоки задержки - его внутренние элементы. Элементы в DolectQueue должны реализовать интерфейс java.util.concurrent.Delayed . Определение этого интерфейса очень простое:
Общедоступный интерфейс задержанный Extends сопоставимо <Doyed> {Long GetDelay (UNIT UNIT);} Возвращаемое значение метода getDelay() - это время удержания до того, как элемент очереди будет выпущен. Если возвращается 0 или负值, это означает, что элемент истек и должен быть выпущен. В настоящее время задержка quidequeue выпустит этот объект через свой метод take() .
Как видно из приведенного выше определения задержки интерфейса, он также наследует Comparable интерфейс. Это связано с тем, что элементы в задержке должны быть отсортированы. Вообще говоря, мы сортируем по приоритету времени истечения срока действия элемента.
Пример 1: Укажите время истечения срока действия объекта
Во -первых, мы определяем элемент, который должен реализовать задержку интерфейса
Общедоступный класс задержка смены задержанный {частное долгое время истекло; частная длинная задержка; Приватное название строки; Задержка седализации (строка elementName, Long Delay) {this. name = elementName; этот. задержка = задержка; Срок действия = (задержка + система. CurrentTimeMillis ()); } @Override public int compareTo (задержка O) {задержка размера CACHED = (DoSeleDelement) O; return cached.getExpired ()> истек? 1: -1; } @Override public long getDelay (UNIT UNIT) {return (expert - System. CurrentTimeMillis ()); } @Override public String toString () {return "doyedEdelement [dower =" + delay + ", name =" + name + "]"; } public long getExpired () {return истек; }}Установите время истечения срока действия этого элемента на 3s
Общедоступный класс задержка quideeexample {public static void main (string [] args) бросает прерывание. Задержка размещения ele = new DelesEledement ("Cache 3 секунды", 3000); queue.put (ele); Система. out.println (queue.take ()); }}Запустите эту основную функцию, и мы можем обнаружить, что нам нужно подождать 3 секунды, прежде чем распечатать этот объект.
Фактически, существует множество сценариев применения для задержки, таких как подключения к закрытию, объекты кэша, обработка тайм -аута и другие сценарии. Давайте сдадим экзамен студентов в качестве примера, чтобы все поняли, что все понимают задержку.
Пример 2: Обратитесь со всеми учащимися на экзамене как к задержке, кто заканчивает вопросы в первую очередь выпускает их
Во -первых, мы строим студенческий объект
Общественный класс учеников реализует выполняемые, отсроченные {частное имя строки; // Назовите частное долгое время; // время для тестовых вопросов частное долгое время; // время для завершения общественного студента (название строки, долгое время) {это. имя = имя; этот. Стоимость = затрат; feltintime = opttime + system. CurrentTimemiLlis (); } @Override public void run () {System. out.println (имя + "Отправить документ, время" + oplime /1000); } @Override public long getDelay (UNIT TimeUnit) {returntime - System. CurrentTimeMillis ()); } @Override public int compareto (задержка O) {студент другой = (студент) o; возврат стоимости> = Другое. Стоимость времени? 1: -1; }}Затем постройте объект учителя, чтобы сдать экзамен для студентов
Учитель открытого класса {статический финал int student_size = 30; public static void main (string [] args) бросает прерывание {случайное r = new random (); // думать обо всех студентах как о задержке задержки задержки <студента> Студенты = Новая задержка questiue <tlond> (); // Создание пула потоков, чтобы студенты "выполняли свою домашнюю работу" Executorservice exec = executors.newfixedthreadpool (student_size); for (int i = 0; i <Tood_Size; i ++) {// Инициализируйте имя студента и время для проведения тестирования. } // запустить тест while (! Student.isempty ()) {exec.execute (stenty.take ()); } exec.shutdown (); }}Давайте посмотрим на результаты бега:
Студент 2 отправьте газету, 3
Студент 1 вручает в статьи, взяв 5
Студент 5 отправьте газету, 7
Студент 4 отправьте газету, взяв 8
Студент 3 отправьте газету, 11
Благодаря результатам выполнения мы можем обнаружить, что каждый студент будет «отправлять документ» после указанного времени запуска ( в зависимости от метода getDelay () ), и статья будет представлена первой ( в зависимости от метода сравнения () ).
Посмотрев на его исходный код, вы можете увидеть, что внутренняя реализация задержки использует PriorityQueue и блокировку:
4.3 LinkedBlockingqueue
Конфигурация размера очереди блокировки LinkedBlockingueue является необязательной. Если мы указываем размер при инициализации, он ограничен, а если не указано, он ограничен. Говорят, что это безгранично, но на самом деле размер по умолчанию - Integer.MAX_VALUE . Его внутренняя реализация является связанным списком.
Как и ArrayBlockingQueue, LinkedBlockingQueue также хранит данные первым в первую очередь. Недавно вставленным объектом является хвост, а недавно перемещенный объект - это голова. Вот пример инициализации и изготовления LinkedBlockingQueue:
Blockquequeue <string> unbounded = new LinkedBlockqueue <string> (); Blockquequeue <string> BAUDED = NEW LINKEDBlockingQueue <string> (1024); MANDED.PUT ("value"); string value = baded.take ();4.4 Приоритетная блокировка
Приоритет BlockingQueue - это очередь без границ, а правила сортировки такие же, как java.util.PriorityQueue . Следует отметить, что нулевые объекты разрешаются вставить в приоритетную блокировку.
Все объекты, вставленные в приоритетную блокировку, должны реализовать интерфейс java.lang.Comparable , а правила сортировки приоритета очереди определяются в соответствии с нашей реализацией этого интерфейса.
Кроме того, мы можем получить итератор от приоритетной блокировки, но этот итератор не гарантирует итерацию в приоритетном порядке.
Давайте приведем пример, чтобы проиллюстрировать. Во -первых, мы определяем тип объекта, который должен реализовать сопоставимый интерфейс:
Public Class PriorityElement реализует сопоставимый <DrivetityElement> {private int priority; // определить приоритет приоритет (int priority) {// Инициализировать приоритет this.priority = приоритет;}@efficepublic int compareto (приоритет o) {// сортировать по приоритетному размеру приоритет> = o.getPriority ()? 1: -1;} public int getPriority () {return privation;} public void setPriority (int priority) {this.priority = priority;}@overridepublic string toString () {return "Затем мы случайным образом устанавливаем приоритет в очередь
public class priorityblockingqueeexample {public static void main (String [] args) Throws refruptedException {priorityblockingqueue <frivationElement> queue = new PriorityBlockingQueue <> (); for (int i = 0; i <5; i ++) {случайный случайный = new random (); Приоритет ele = новый приоритет (random.nextint (10)); queue.put (ele); } while (! queue.isempty ()) {System.out.println (queue.take ()); }}}Проверьте результаты работы:
Приоритет [Приоритет = 3]
Приоритет [Приоритет = 4]
Приоритет [Приоритет = 5]
Приоритет [Приоритет = 8]
Приоритет [Приоритет = 9]
4.5 Synchronousqueue
Только один элемент разрешен внутри очереди Synchronousqueue. Когда поток вставляет элемент, он будет заблокирован, если элемент не будет потреблен другим потоком.
Выше всего содержание этой статьи. Я надеюсь, что это будет полезно для каждого обучения, и я надеюсь, что все будут поддерживать Wulin.com больше.