1. Въведение
В този урок ще обсъдим интерфейса на Java Queue .
Първо ще вземе поглед към това, което е на опашката прави, а някои от своите основни методи . След това ще се потопим в редица внедрения, които Java предлага като стандарт.
И накрая, ще говорим за безопасността на нишките, преди да завършим всичко.
2. Визуализиране на опашката
Нека започнем с бърза аналогия.
Представете си, че току-що отворихме първия си бизнес - щанд за хотдог. Искаме да обслужваме новите си потенциални клиенти по възможно най-ефективния начин за нашия малък бизнес; един по един. Първо ги молим да оформят подредена линия пред нашия щанд, като отзад се присъединяват нови клиенти. Благодарение на нашите организационни умения, вече можем да разпространяваме нашите вкусни хот-доги по справедлив начин.
Опашките в Java работят по подобен начин. След като декларираме нашата опашка, можем да добавим нови елементи отзад и да ги премахнем отпред.
Всъщност, повечето Опашки, които ще срещнем в Java, работят по този първи, първи изходящ начин - често съкратен на FIFO.
Има обаче едно изключение, което ще засегнем по-късно.
3. Основни методи
На опашката декларира редица методи, които трябва да бъдат кодирани от всички класове прилагане. Нека очертаем няколко от най-важните сега:
- offer () - Вмъква нов елемент в опашката
- poll () - Премахва елемент от предната страна на опашката
- peek () - Проверява елемента отпред на опашката, без да го премахва
4. Абстрактна опашка
AbstractQueue е възможно най -простата реализация на Queue, която Java предоставя. Включва скелетна реализация на някои от методите на интерфейса на опашката , с изключение на офертата .
Когато създаваме персонализирана опашка, разширяваща класа AbstractQueue , трябва да осигурим изпълнение на метода на оферта , който не позволява вмъкването на нулеви елементи.
Освен това, ние трябва да предостави на методите надничали, анкета, размер, и java.util е итератор .
Нека да съберем проста реализация на Queue, използвайки AbstractQueue.
Първо, нека дефинираме нашия клас с LinkedList, за да съхраняваме елементите на нашата опашка :
public class CustomBaeldungQueue extends AbstractQueue { private LinkedList elements; public CustomBaeldungQueue() { this.elements = new LinkedList(); } }
След това нека заменим необходимите методи и предоставим кода:
@Override public Iterator iterator() { return elements.iterator(); } @Override public int size() { return elements.size(); } @Override public boolean offer(T t) { if(t == null) return false; elements.add(t); return true; } @Override public T poll() { Iterator iter = elements.iterator(); T t = iter.next(); if(t != null){ iter.remove(); return t; } return null; } @Override public T peek() { return elements.getFirst(); }
Отлично, нека проверим дали работи с бърз единичен тест:
customQueue.add(7); customQueue.add(5); int first = customQueue.poll(); int second = customQueue.poll(); assertEquals(7, first); assertEquals(5, second);
4. Подинтерфейси
Обикновено интерфейсът на опашката се наследява от 3 основни подинтерфейса. Блокиране на опашки, опашки за прехвърляне и Deques .
Заедно тези 3 интерфейса са внедрени от по-голямата част от наличните Опашки на Java . Нека да разгледаме набързо какво са направили тези интерфейси.
4.1. Блокиране на опашки
В BlockingQueue интерфейс поддържа допълнителни операции, които силови нишки, за да чакат на опашка в зависимост от текущото състояние. Нишка може да чака в опашката да не е празна при опит за извличане или тя да се изпразни при добавяне на нов елемент.
Стандартните опашки за блокиране включват LinkedBlockingQueue, SynchronousQueue и ArrayBlockingQueue .
За повече информация се насочете към нашата статия за блокиране на опашки .
4.2. Опашки за прехвърляне
Интерфейсът TransferQueue разширява интерфейса BlockingQueue, но е съобразен с модела производител-потребител. Той контролира потока на информация от производител към потребител, създавайки обратно налягане в системата.
Java се доставя с една реализация на интерфейса TransferQueue , LinkedTransferQueue.
4.3. Декес
Deque е съкращение от D ouble- E nded Que ue и е аналог на тесте карти - елементи могат да бъдат взети както от началото, така и от края на Deque . Много прилича на традиционната опашка, за Deque предоставя методи за добавяне, извличане и поглед на елементите, съдържащи както на горната и долната част .
За подробно ръководство за това как Deque работи, проверете нашия ArrayDeque статия.
5. Приоритетни опашки
По-рано видяхме, че повечето от Опашките , които срещаме в Java, следват принципа FIFO.
Едно такова изключение от това правило е PriorityQueue . Когато в Приоритетната опашка се вмъкват нови елементи , те се подреждат въз основа на естественото им подреждане или от дефиниран Сравнител, предоставен, когато изграждаме Приоритетна опашка .
Нека да разгледаме как работи това с прост единичен тест:
PriorityQueue integerQueue = new PriorityQueue(); integerQueue.add(9); integerQueue.add(2); integerQueue.add(4); int first = integerQueue.poll(); int second = integerQueue.poll(); int third = integerQueue.poll(); assertEquals(2, first); assertEquals(4, second); assertEquals(9, third);
Въпреки реда, в който нашите цели числа бяха добавени към приоритетната опашка , можем да видим, че редът за извличане се променя според естествения ред на числата.
Можем да видим, че същото важи и когато се прилага към низове :
PriorityQueue stringQueue = new PriorityQueue(); stringQueue.add("blueberry"); stringQueue.add("apple"); stringQueue.add("cherry"); String first = stringQueue.poll(); String second = stringQueue.poll(); String third = stringQueue.poll(); assertEquals("apple", first); assertEquals("blueberry", second); assertEquals("cherry", third);
6. Безопасност на резбата
Adding items to Queues is particularly useful in multi-threaded environments. A Queue can be shared amongst threads, and be used to block progress until space is available – helping us overcome some common multi-threaded problems.
For example, writing to a single disk from multiple threads creates resource contention and can lead to slow writing times. Creating a single writer thread with a BlockingQueue can alleviate this issue and lead to vastly improved write speeds.
Luckily, Java offers ConcurrentLinkedQueue, ArrayBlockingQueue, and ConcurrentLinkedDeque which are thread-safe and perfect for multi-threaded programs.
7. Conclusion
В този урок се задълбочихме в интерфейса на Java Queue .
На първо място, ние изследва каква опашка прави , както и внедряванията, че Java предоставя.
След това разгледахме обичайния FIFO принцип на опашката , както и приоритетната опашка, която се различава в подреждането.
И накрая, изследвахме безопасността на нишките и как опашките могат да се използват в среда с много нишки.
Както винаги, кодът е достъпен в GitHub.