Java for Beginner pinned «Вчера мы провели трансляцию в канале по решению задач с Codewar. Устраивает ли вас такой формат, нужно ли делать запись, для пересмотра?»
LinkedBlockingQueue, отличия от других очередей.
LinkedBlockingQueue — это реализация блокирующей очереди на основе связанного списка, предоставляемая в пакете java.util.concurrent. Она поддерживает опциональную ограниченную емкость и используется для передачи данных между потоками с возможностью блокировки.
Основные отличия от других очередей:
Блокирующая очередь: Ожидает свободного места для добавления или доступного элемента для извлечения.
Основана на связанном списке: В отличие от ArrayBlockingQueue, которая использует массив, LinkedBlockingQueue использует связанный список.
Опциональная ограниченная емкость: Вы можете задать максимальную емкость очереди. По умолчанию емкость не ограничена.
Внутреннее устройство
LinkedBlockingQueue реализует блокирующую очередь с использованием двух внутренних объектов Node, а также использует механизмы блокировок для управления доступом к очереди.
Основные компоненты:
Внутренний класс Node:
Узел, содержащий данные и ссылку на следующий элемент в очереди.
Голова и хвост очереди:
head: Ссылка на первый узел в очереди.
last: Ссылка на последний узел в очереди.
Механизмы блокировки:
Две раздельные блокировки для вставки и удаления: putLock и takeLock.
Принцип работы:
Вставка элемента (put):
Захватывается блокировка putLock.
Проверяется, не превышает ли очередь максимальную емкость.
Создается новый узел и добавляется в конец очереди.
Если очередь была пустой, сигнализируется о наличии новых элементов (notEmpty.signal()).
Освобождается блокировка putLock.
Извлечение элемента (take):
Захватывается блокировка takeLock.
Проверяется, не пустая ли очередь.
Удаляется узел из начала очереди.
Если очередь была заполнена, сигнализируется о наличии свободного места (notFull.signal()).
Освобождается блокировка takeLock.
Ссылки на полезные статьи (спасибо авторам за проделанную работу) :
https://www.geeksforgeeks.org/linkedblockingqueue-class-in-java/
https://www.baeldung.com/java-queue-linkedblocking-concurrentlinked
#Java #Training #Medium #LinkedBlockingQueue
LinkedBlockingQueue — это реализация блокирующей очереди на основе связанного списка, предоставляемая в пакете java.util.concurrent. Она поддерживает опциональную ограниченную емкость и используется для передачи данных между потоками с возможностью блокировки.
Основные отличия от других очередей:
Блокирующая очередь: Ожидает свободного места для добавления или доступного элемента для извлечения.
Основана на связанном списке: В отличие от ArrayBlockingQueue, которая использует массив, LinkedBlockingQueue использует связанный список.
Опциональная ограниченная емкость: Вы можете задать максимальную емкость очереди. По умолчанию емкость не ограничена.
import java.util.concurrent.LinkedBlockingQueue;
public class LinkedBlockingQueueExample {
public static void main(String[] args) {
LinkedBlockingQueue<Integer> queue = new LinkedBlockingQueue<>(10);
try {
queue.put(1);
queue.put(2);
System.out.println(queue.take());
System.out.println(queue.take());
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
Внутреннее устройство
LinkedBlockingQueue реализует блокирующую очередь с использованием двух внутренних объектов Node, а также использует механизмы блокировок для управления доступом к очереди.
Основные компоненты:
Внутренний класс Node:
Узел, содержащий данные и ссылку на следующий элемент в очереди.
static class Node<E> {
E item;
Node<E> next;
Node(E x) { item = x; }
}
Голова и хвост очереди:
head: Ссылка на первый узел в очереди.
last: Ссылка на последний узел в очереди.
private transient Node<E> head;
private transient Node<E> last;
Механизмы блокировки:
Две раздельные блокировки для вставки и удаления: putLock и takeLock.
private final ReentrantLock putLock = new ReentrantLock();
private final Condition notFull = putLock.newCondition();
private final ReentrantLock takeLock = new ReentrantLock();
private final Condition notEmpty = takeLock.newCondition();
Принцип работы:
Вставка элемента (put):
Захватывается блокировка putLock.
Проверяется, не превышает ли очередь максимальную емкость.
Создается новый узел и добавляется в конец очереди.
Если очередь была пустой, сигнализируется о наличии новых элементов (notEmpty.signal()).
Освобождается блокировка putLock.
Извлечение элемента (take):
Захватывается блокировка takeLock.
Проверяется, не пустая ли очередь.
Удаляется узел из начала очереди.
Если очередь была заполнена, сигнализируется о наличии свободного места (notFull.signal()).
Освобождается блокировка takeLock.
import java.util.concurrent.LinkedBlockingQueue;
public class LinkedBlockingQueueExample {
public static void main(String[] args) {
LinkedBlockingQueue<Integer> queue = new LinkedBlockingQueue<>(2);
// Вставка элементов
new Thread(() -> {
try {
queue.put(1);
System.out.println("Inserted 1");
queue.put(2);
System.out.println("Inserted 2");
queue.put(3);
System.out.println("Inserted 3");
} catch (InterruptedException e) {
e.printStackTrace();
}
}).start();
// Извлечение элементов
new Thread(() -> {
try {
Thread.sleep(2000);
System.out.println("Removed " + queue.take());
System.out.println("Removed " + queue.take());
System.out.println("Removed " + queue.take());
} catch (InterruptedException e) {
e.printStackTrace();
}
}).start();
}
}
Ссылки на полезные статьи (спасибо авторам за проделанную работу) :
https://www.geeksforgeeks.org/linkedblockingqueue-class-in-java/
https://www.baeldung.com/java-queue-linkedblocking-concurrentlinked
#Java #Training #Medium #LinkedBlockingQueue
GeeksforGeeks
LinkedBlockingQueue Class in Java - GeeksforGeeks
A Computer Science portal for geeks. It contains well written, well thought and well explained computer science and programming articles, quizzes and practice/competitive programming/company interview Questions.
Что выведет код?
#Tasks
import java.util.concurrent.LinkedBlockingQueue;
public class LinkedBlockingQueueChallenge {
public static void main(String[] args) throws InterruptedException {
LinkedBlockingQueue<Integer> queue = new LinkedBlockingQueue<>();
for (int i = 0; i < 10; i++) {
queue.put(i);
}
int result = 0;
while (!queue.isEmpty()) {
result += queue.take();
if (!queue.isEmpty()) {
queue.put(queue.take() * 2);
}
}
System.out.println("Result: " + result);
}
}
#Tasks
Основные методы LinkedBlockingQueue
put(E e):
Вставляет элемент в конец очереди. Если очередь заполнена, блокируется до освобождения места.
take():
Извлекает и удаляет элемент из начала очереди. Если очередь пуста, блокируется до появления элемента.
offer(E e):
Вставляет элемент в конец очереди, если есть свободное место. Возвращает true, если элемент был добавлен, иначе false.
poll():
Извлекает и удаляет элемент из начала очереди. Возвращает null, если очередь пуста.
peek():
Возвращает элемент из начала очереди без его удаления. Возвращает null, если очередь пуста.
remainingCapacity():
Возвращает количество свободных мест в очереди.
drainTo(Collection<? super E> c):
Перемещает все доступные элементы в указанную коллекцию.
clear():
Удаляет все элементы из очереди.
Примеры использования
Производитель-потребитель:
Очередь задач:
#Java #Training #Medium #LinkedBlockingQueue
put(E e):
Вставляет элемент в конец очереди. Если очередь заполнена, блокируется до освобождения места.
LinkedBlockingQueue<Integer> queue = new LinkedBlockingQueue<>(2);
queue.put(1);
queue.put(2);
take():
Извлекает и удаляет элемент из начала очереди. Если очередь пуста, блокируется до появления элемента.
Integer item = queue.take();
System.out.println(item);
offer(E e):
Вставляет элемент в конец очереди, если есть свободное место. Возвращает true, если элемент был добавлен, иначе false.
boolean added = queue.offer(3);
System.out.println(added); // false, если очередь заполнена
poll():
Извлекает и удаляет элемент из начала очереди. Возвращает null, если очередь пуста.
Integer item = queue.poll();
System.out.println(item);
peek():
Возвращает элемент из начала очереди без его удаления. Возвращает null, если очередь пуста.
Integer item = queue.peek();
System.out.println(item);
remainingCapacity():
Возвращает количество свободных мест в очереди.
int capacity = queue.remainingCapacity();
System.out.println(capacity);
drainTo(Collection<? super E> c):
Перемещает все доступные элементы в указанную коллекцию.
List<Integer> list = new ArrayList<>();
queue.drainTo(list);
System.out.println(list);
clear():
Удаляет все элементы из очереди.
queue.clear();
Примеры использования
Производитель-потребитель:
import java.util.concurrent.LinkedBlockingQueue;
public class ProducerConsumerExample {
public static void main(String[] args) {
LinkedBlockingQueue<Integer> queue = new LinkedBlockingQueue<>(5);
// Производитель
new Thread(() -> {
try {
for (int i = 0; i < 10; i++) {
queue.put(i);
System.out.println("Produced: " + i);
}
} catch (InterruptedException e) {
Thread.currentThread().interrupt();
}
}).start();
// Потребитель
new Thread(() -> {
try {
for (int i = 0; i < 10; i++) {
Integer item = queue.take();
System.out.println("Consumed: " + item);
}
} catch (InterruptedException e) {
Thread.currentThread().interrupt();
}
}).start();
}
}
Очередь задач:
import java.util.concurrent.LinkedBlockingQueue;
public class TaskQueueExample {
public static void main(String[] args) {
LinkedBlockingQueue<Runnable> taskQueue = new LinkedBlockingQueue<>(10);
// Запуск потока исполнителя задач
new Thread(() -> {
while (true) {
try {
Runnable task = taskQueue.take();
task.run();
} catch (InterruptedException e) {
Thread.currentThread().interrupt();
}
}
}).start();
// Добавление задач в очередь
taskQueue.offer(() -> System.out.println("Task 1 executed"));
taskQueue.offer(() -> System.out.println("Task 2 executed"));
}
}
#Java #Training #Medium #LinkedBlockingQueue
This media is not supported in your browser
VIEW IN TELEGRAM
Доброе утро!
Напоминаю, что сегодня в 16:00 по МСК, мы вновь встречаемся, чтобы разобрать структурные паттерны проектирования.
Запасайтесь хорошим настроением и печеньками, ждем всех!
🖐
Напоминаю, что сегодня в 16:00 по МСК, мы вновь встречаемся, чтобы разобрать структурные паттерны проектирования.
Запасайтесь хорошим настроением и печеньками, ждем всех!
🖐
Запись нашей сегодняшней встречи -
https://youtu.be/_jnIaJz_mJc
https://rutube.ru/video/506c291cd9b61894b4c99ac8c168e115/
Огромный респект тем кто смог прийти, за участие и подсказки!
@Alexander_Gors отдельное спасибо, за лайф-кодинг!)
Сегодня, мы совместно рассмотрели на примерах структурные паттерны проектирования:
- Адаптер (Adapter)
- Мост(Bridge)
- Компоновщик (Composite)
- Декоратор (Decorator, Wrapper)
- Фасад (Facade)
- Легковес (Flyweight)
- Заместитель (Proxy)
Смотрите, комментируйте, задавайте вопросы! Обязательно подписывайтесь на ютуб и рутюб каналы!!!
Гит репозиторий с результатом - https://github.com/Oleborn/PatternsOfCoding
Всем теплой ночи и легкой рабочей недели! 🫡✌️
https://youtu.be/_jnIaJz_mJc
https://rutube.ru/video/506c291cd9b61894b4c99ac8c168e115/
Огромный респект тем кто смог прийти, за участие и подсказки!
@Alexander_Gors отдельное спасибо, за лайф-кодинг!)
Сегодня, мы совместно рассмотрели на примерах структурные паттерны проектирования:
- Адаптер (Adapter)
- Мост(Bridge)
- Компоновщик (Composite)
- Декоратор (Decorator, Wrapper)
- Фасад (Facade)
- Легковес (Flyweight)
- Заместитель (Proxy)
Смотрите, комментируйте, задавайте вопросы! Обязательно подписывайтесь на ютуб и рутюб каналы!!!
Гит репозиторий с результатом - https://github.com/Oleborn/PatternsOfCoding
Всем теплой ночи и легкой рабочей недели! 🫡✌️
Встреча_в_Телемосте_11_08_24_20_03_54_—_запись.webm
227 MB
Для тех кто не смог победить блокировку Youtube и не желает заходить в Rutube выкладываю видео тут!
Смотрите на здоровье) 🫡
Но с вас подписка на Youtube и Rutube и делитесь этими видео, буду крайне благодарен!)))
#online_meeting
Смотрите на здоровье) 🫡
#online_meeting
ConcurrentLinkedQueue, внутреннее устройство, особенности и преимущества
ConcurrentLinkedQueue — это неконкурирующая неблокирующая очередь на основе связанного списка, предоставляемая в пакете java.util.concurrent. Она поддерживает высокую степень конкурентности благодаря использованию алгоритмов без блокировок (lock-free algorithms).
Особенности и преимущества
Неконкурирующая: Методы ConcurrentLinkedQueue реализованы таким образом, что могут использоваться несколькими потоками одновременно без необходимости явной синхронизации.
Неблокирующая: Основана на алгоритмах без блокировок, что позволяет избежать блокировок и взаимных блокировок, повышая производительность в условиях высокой конкурентности.
Поддержка FIFO (First-In-First-Out): Гарантирует, что элементы будут обрабатываться в порядке их добавления.
Внутреннее устройство
ConcurrentLinkedQueue использует алгоритм Майкла-скотта (Michael-Scott) для реализации неблокирующей очереди на основе связанного списка. Основные компоненты включают узлы (nodes) и ссылки на голову (head) и хвост (tail) очереди.
Внутренний класс Node:
Узел содержит элемент данных и ссылку на следующий узел.
Голова и хвост очереди:
Очередь хранит ссылки на голову и хвост, которые используются для вставки и удаления элементов.
Алгоритм Майкла-скотта:
Этот алгоритм основан на атомарных операциях, таких как compareAndSet, для безопасного обновления ссылок на узлы без использования блокировок.
Преимущества использования
Высокая производительность в многопоточных средах: Благодаря отсутствию блокировок, ConcurrentLinkedQueue показывает высокую производительность даже при большом количестве конкурирующих потоков.
Минимизация блокировок и ожиданий: Использование атомарных операций позволяет избежать задержек, связанных с блокировками.
Безопасность при многопоточном доступе: Методы очереди обеспечивают безопасность при доступе из нескольких потоков без дополнительной синхронизации.
Ссылки на полезные статьи (спасибо авторам за проделанную работу) :
https://www.baeldung.com/java-queue-linkedblocking-concurrentlinked
https://www.geeksforgeeks.org/concurrentlinkedqueue-in-java-with-examples/
#Java #Training #Medium #ConcurrentLinkedQueue
ConcurrentLinkedQueue — это неконкурирующая неблокирующая очередь на основе связанного списка, предоставляемая в пакете java.util.concurrent. Она поддерживает высокую степень конкурентности благодаря использованию алгоритмов без блокировок (lock-free algorithms).
Особенности и преимущества
Неконкурирующая: Методы ConcurrentLinkedQueue реализованы таким образом, что могут использоваться несколькими потоками одновременно без необходимости явной синхронизации.
Неблокирующая: Основана на алгоритмах без блокировок, что позволяет избежать блокировок и взаимных блокировок, повышая производительность в условиях высокой конкурентности.
Поддержка FIFO (First-In-First-Out): Гарантирует, что элементы будут обрабатываться в порядке их добавления.
Внутреннее устройство
ConcurrentLinkedQueue использует алгоритм Майкла-скотта (Michael-Scott) для реализации неблокирующей очереди на основе связанного списка. Основные компоненты включают узлы (nodes) и ссылки на голову (head) и хвост (tail) очереди.
Внутренний класс Node:
Узел содержит элемент данных и ссылку на следующий узел.
private static class Node<E> {
volatile E item;
volatile Node<E> next;
Node(E item) {
this.item = item;
}
}
Голова и хвост очереди:
Очередь хранит ссылки на голову и хвост, которые используются для вставки и удаления элементов.
private transient volatile Node<E> head;
private transient volatile Node<E> tail;
Алгоритм Майкла-скотта:
Этот алгоритм основан на атомарных операциях, таких как compareAndSet, для безопасного обновления ссылок на узлы без использования блокировок.
public boolean offer(E e) {
final Node<E> newNode = new Node<>(e);
for (Node<E> t = tail, p = t; ; ) {
Node<E> q = p.next;
if (q == null) {
if (p.next = q) {
tail = newNode;
return true;
}
} else {
p = (t != tail) ? tail : q;
}
}
}
Преимущества использования
Высокая производительность в многопоточных средах: Благодаря отсутствию блокировок, ConcurrentLinkedQueue показывает высокую производительность даже при большом количестве конкурирующих потоков.
Минимизация блокировок и ожиданий: Использование атомарных операций позволяет избежать задержек, связанных с блокировками.
Безопасность при многопоточном доступе: Методы очереди обеспечивают безопасность при доступе из нескольких потоков без дополнительной синхронизации.
import java.util.concurrent.ConcurrentLinkedQueue;
public class ConcurrentLinkedQueueExample {
public static void main(String[] args) {
ConcurrentLinkedQueue<Integer> queue = new ConcurrentLinkedQueue<>();
// Вставка элементов
queue.offer(1);
queue.offer(2);
queue.offer(3);
// Извлечение элементов
System.out.println(queue.poll()); // 1
System.out.println(queue.poll()); // 2
System.out.println(queue.poll()); // 3
}
}
Ссылки на полезные статьи (спасибо авторам за проделанную работу) :
https://www.baeldung.com/java-queue-linkedblocking-concurrentlinked
https://www.geeksforgeeks.org/concurrentlinkedqueue-in-java-with-examples/
#Java #Training #Medium #ConcurrentLinkedQueue
Baeldung
LinkedBlockingQueue vs ConcurrentLinkedQueue | Baeldung
Learn the difference between LinkedBlockingQueue and ConcurrentLinkedQueue in Java
Что выведет код?
#Tasks
import java.util.concurrent.ConcurrentLinkedQueue;
public class ConcurrentLinkedQueueChallenge {
public static void main(String[] args) {
ConcurrentLinkedQueue<Integer> queue = new ConcurrentLinkedQueue<>();
for (int i = 1; i <= 5; i++) {
queue.offer(i);
}
int result = 1;
for (int i = 0; i < 3; i++) {
Integer val = queue.poll();
if (val != null) {
result *= val;
}
queue.offer(result);
}
int sum = 0;
for (Integer val : queue) {
sum += val;
}
System.out.println("Sum: " + sum);
}
}
#Tasks
Мем для IQ > 100!😱
Внимание! Возможен перелом мозга! Будьте внимательнее!!!
https://t.me/Java_for_beginner_dev
#Mems
https://t.me/Java_for_beginner_dev
#Mems
Основные методы ConcurrentLinkedQueue и примеры использования
offer(E e):
Вставляет элемент в конец очереди. Возвращает true после успешного добавления.
poll():
Извлекает и удаляет элемент из головы очереди. Возвращает null, если очередь пуста.
peek():
Возвращает элемент из головы очереди без его удаления. Возвращает null, если очередь пуста.
isEmpty():
Проверяет, пуста ли очередь.
size():
Возвращает количество элементов в очереди. Обратите внимание, что этот метод может быть дорогим, так как требует полной итерации по очереди для подсчета элементов.
Примеры использования
Производитель-потребитель:
Очередь задач:
#Java #Training #Medium #ConcurrentLinkedQueue
offer(E e):
Вставляет элемент в конец очереди. Возвращает true после успешного добавления.
ConcurrentLinkedQueue<Integer> queue = new ConcurrentLinkedQueue<>();
queue.offer(1);
queue.offer(2);
poll():
Извлекает и удаляет элемент из головы очереди. Возвращает null, если очередь пуста.
Integer item = queue.poll();
System.out.println(item); // 1
peek():
Возвращает элемент из головы очереди без его удаления. Возвращает null, если очередь пуста.
Integer item = queue.peek();
System.out.println(item); // 2
isEmpty():
Проверяет, пуста ли очередь.
boolean isEmpty = queue.isEmpty();
System.out.println(isEmpty); // false
size():
Возвращает количество элементов в очереди. Обратите внимание, что этот метод может быть дорогим, так как требует полной итерации по очереди для подсчета элементов.
int size = queue.size();
System.out.println(size); // 1
Примеры использования
Производитель-потребитель:
import java.util.concurrent.ConcurrentLinkedQueue;
public class ProducerConsumerExample {
public static void main(String[] args) {
ConcurrentLinkedQueue<Integer> queue = new ConcurrentLinkedQueue<>();
// Производитель
new Thread(() -> {
for (int i = 0; i < 10; i++) {
queue.offer(i);
System.out.println("Produced: " + i);
}
}).start();
// Потребитель
new Thread(() -> {
for (int i = 0; i < 10; i++) {
Integer item;
while ((item = queue.poll()) == null) {
// Ожидание элемента
}
System.out.println("Consumed: " + item);
}
}).start();
}
}
Очередь задач:
import java.util.concurrent.ConcurrentLinkedQueue;
public class TaskQueueExample {
public static void main(String[] args) {
ConcurrentLinkedQueue<Runnable> taskQueue = new ConcurrentLinkedQueue<>();
// Запуск потока исполнителя задач
new Thread(() -> {
while (true) {
Runnable task = taskQueue.poll();
if (task != null) {
task.run();
}
}
}).start();
// Добавление задач в очередь
taskQueue.offer(() -> System.out.println("Task 1 executed"));
taskQueue.offer(() -> System.out.println("Task 2 executed"));
}
}
#Java #Training #Medium #ConcurrentLinkedQueue
DelayQueue, внутреннее устройство и преимущества
DelayQueue — это специализированная очередь из пакета java.util.concurrent, которая предназначена для хранения элементов до истечения их задержки. Она основана на приоритетной очереди и используется в ситуациях, где необходимо реализовать задержку выполнения задач.
Внутреннее устройство DelayQueue
DelayQueue реализует интерфейсы BlockingQueue и Queue. Она состоит из элементов, которые должны реализовать интерфейс Delayed. Этот интерфейс требует реализации метода getDelay(TimeUnit unit), который возвращает оставшееся время задержки элемента в указанных единицах.
Элементы DelayQueue:
Каждый элемент в DelayQueue должен реализовать интерфейс Delayed.
Внутренняя структура:
DelayQueue использует приоритетную очередь для хранения элементов. Это позволяет эффективно управлять элементами на основе их времени задержки.
Приоритетная очередь реализуется на основе кучи (heap), что обеспечивает логарифмическое время выполнения операций вставки и удаления.
Механизм блокировки:
DelayQueue использует методы ReentrantLock для обеспечения потокобезопасности. Это позволяет избежать гонок и обеспечивает корректное поведение в многопоточной среде.
Извлечение элементов:
При попытке извлечения элемента из DelayQueue, если задержка элемента еще не истекла, поток будет заблокирован до истечения задержки.
Преимущества DelayQueue
Управление задержками: DelayQueue идеально подходит для задач, где необходимо управлять задержками, таких как планирование задач или кэширование с истечением времени.
Потокобезопасность: Использование механизмов блокировки и приоритетной очереди обеспечивает безопасность в многопоточных приложениях.
Гибкость: Возможность использовать любые объекты, реализующие интерфейс Delayed, позволяет легко адаптировать DelayQueue под различные задачи.
Ссылки на полезные статьи (спасибо авторам за проделанную работу) :
https://www.baeldung.com/java-delay-queue
https://habr.com/ru/articles/599603/
#Java #Training #Medium #DelayQueue
DelayQueue — это специализированная очередь из пакета java.util.concurrent, которая предназначена для хранения элементов до истечения их задержки. Она основана на приоритетной очереди и используется в ситуациях, где необходимо реализовать задержку выполнения задач.
Внутреннее устройство DelayQueue
DelayQueue реализует интерфейсы BlockingQueue и Queue. Она состоит из элементов, которые должны реализовать интерфейс Delayed. Этот интерфейс требует реализации метода getDelay(TimeUnit unit), который возвращает оставшееся время задержки элемента в указанных единицах.
Элементы DelayQueue:
Каждый элемент в DelayQueue должен реализовать интерфейс Delayed.
import java.util.concurrent.Delayed;
import java.util.concurrent.TimeUnit;
class DelayedElement implements Delayed {
private final long delayTime;
private final long creationTime;
public DelayedElement(long delayTime) {
this.delayTime = delayTime;
this.creationTime = System.currentTimeMillis();
}
@Override
public long getDelay(TimeUnit unit) {
long elapsedTime = System.currentTimeMillis() - creationTime;
return unit.convert(delayTime - elapsedTime, TimeUnit.MILLISECONDS);
}
@Override
public int compareTo(Delayed o) {
if (this.getDelay(TimeUnit.MILLISECONDS) < o.getDelay(TimeUnit.MILLISECONDS)) {
return -1;
}
if (this.getDelay(TimeUnit.MILLISECONDS) > o.getDelay(TimeUnit.MILLISECONDS)) {
return 1;
}
return 0;
}
}
Внутренняя структура:
DelayQueue использует приоритетную очередь для хранения элементов. Это позволяет эффективно управлять элементами на основе их времени задержки.
Приоритетная очередь реализуется на основе кучи (heap), что обеспечивает логарифмическое время выполнения операций вставки и удаления.
Механизм блокировки:
DelayQueue использует методы ReentrantLock для обеспечения потокобезопасности. Это позволяет избежать гонок и обеспечивает корректное поведение в многопоточной среде.
private final transient ReentrantLock lock = new ReentrantLock();
private final Condition available = lock.newCondition();
Извлечение элементов:
При попытке извлечения элемента из DelayQueue, если задержка элемента еще не истекла, поток будет заблокирован до истечения задержки.
public E take() throws InterruptedException {
final ReentrantLock lock = this.lock;
lock.lockInterruptibly();
try {
for (;;) {
E first = q.peek();
if (first == null) {
available.await();
} else {
long delay = first.getDelay(TimeUnit.NANOSECONDS);
if (delay <= 0) {
return q.poll();
}
first = null;
available.awaitNanos(delay);
}
}
} finally {
lock.unlock();
}
}
Преимущества DelayQueue
Управление задержками: DelayQueue идеально подходит для задач, где необходимо управлять задержками, таких как планирование задач или кэширование с истечением времени.
Потокобезопасность: Использование механизмов блокировки и приоритетной очереди обеспечивает безопасность в многопоточных приложениях.
Гибкость: Возможность использовать любые объекты, реализующие интерфейс Delayed, позволяет легко адаптировать DelayQueue под различные задачи.
Ссылки на полезные статьи (спасибо авторам за проделанную работу) :
https://www.baeldung.com/java-delay-queue
https://habr.com/ru/articles/599603/
#Java #Training #Medium #DelayQueue
Хабр
Полезные и неизвестные возможности Java
В этой статье вы узнаете о некоторых полезных функциях Java, о которых вы, вероятно, не слышали. Это мой личный список функций, использованных мной недавно или с которыми я столкнулся при чтении...
Что выведет код?
#Tasks
import java.util.concurrent.DelayQueue;
import java.util.concurrent.Delayed;
import java.util.concurrent.TimeUnit;
class DelayedElement implements Delayed {
private final long delayTime;
private final long creationTime;
public DelayedElement(long delayTime) {
this.delayTime = delayTime;
this.creationTime = System.currentTimeMillis();
}
@Override
public long getDelay(TimeUnit unit) {
long diff = creationTime + delayTime - System.currentTimeMillis();
return unit.convert(diff, TimeUnit.MILLISECONDS);
}
@Override
public int compareTo(Delayed o) {
return Long.compare(this.getDelay(TimeUnit.MILLISECONDS), o.getDelay(TimeUnit.MILLISECONDS));
}
@Override
public String toString() {
return "DelayedElement{" + "delayTime=" + delayTime + '}';
}
}
public class DelayQueueChallenge {
public static void main(String[] args) throws InterruptedException {
DelayQueue<DelayedElement> queue = new DelayQueue<>();
queue.offer(new DelayedElement(1000));
queue.offer(new DelayedElement(2000));
queue.offer(new DelayedElement(3000));
long startTime = System.currentTimeMillis();
int sum = 0;
for (int i = 0; i < 3; i++) {
DelayedElement element = queue.take();
long elapsedTime = (System.currentTimeMillis() - startTime) / 1000;
sum += elapsedTime;
System.out.println("Taken: " + element + " at " + elapsedTime + " seconds");
}
System.out.println("Sum: " + sum);
}
}
#Tasks