Java for Beginner
675 subscribers
558 photos
156 videos
12 files
851 links
Канал от новичков для новичков!
Изучайте Java вместе с нами!
Здесь мы обмениваемся опытом и постоянно изучаем что-то новое!

Наш YouTube канал - https://www.youtube.com/@Java_Beginner-Dev

Наш канал на RUTube - https://rutube.ru/channel/37896292/
Download Telegram
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
Основные методы DelayQueue и примеры использования

add(E e):

Добавляет элемент в очередь. Если очередь полна, генерируется исключение.
DelayQueue<DelayedElement> delayQueue = new DelayQueue<>();
delayQueue.add(new DelayedElement(1000));


put(E e):

Добавляет элемент в очередь. Если очередь полна, операция блокируется до освобождения места.
delayQueue.put(new DelayedElement(2000));


offer(E e):

Добавляет элемент в очередь, если это возможно. Возвращает true, если элемент был добавлен, и false в противном случае.
boolean added = delayQueue.offer(new DelayedElement(3000));


take():

Извлекает и удаляет элемент из головы очереди, ожидая при необходимости до истечения задержки.
DelayedElement element = delayQueue.take();


poll(long timeout, TimeUnit unit):

Извлекает и удаляет элемент из головы очереди, ожидая до указанного времени, если необходимо.
DelayedElement element = delayQueue.poll(2, TimeUnit.SECONDS);


clear():

Удаляет все элементы из очереди.
delayQueue.clear();


remove(Object o):

Удаляет указанный элемент из очереди, если он присутствует.
delayQueue.remove(someElement);


Примеры использования

Запланированные задачи:
DelayQueue можно использовать для планирования выполнения задач через определенные промежутки времени.
import java.util.concurrent.DelayQueue;

public class ScheduledTaskExample {
public static void main(String[] args) throws InterruptedException {
DelayQueue<DelayedElement> delayQueue = new DelayQueue<>();

// Добавление задач
delayQueue.put(new DelayedElement(3000)); // 3 секунды задержки
delayQueue.put(new DelayedElement(5000)); // 5 секунд задержки

// Обработка задач
while (!delayQueue.isEmpty()) {
DelayedElement element = delayQueue.take();
System.out.println("Task executed: " + element);
}
}
}


Кэширование с истечением срока действия:

DelayQueue можно использовать для реализации кэша, элементы которого удаляются по истечении определенного времени.
import java.util.concurrent.DelayQueue;

public class CacheExample {
private static class CacheItem implements Delayed {
private final String value;
private final long expiryTime;

public CacheItem(String value, long delay) {
this.value = value;
this.expiryTime = System.currentTimeMillis() + delay;
}

@Override
public long getDelay(TimeUnit unit) {
long delay = expiryTime - System.currentTimeMillis();
return unit.convert(delay, TimeUnit.MILLISECONDS);
}

@Override
public int compareTo(Delayed o) {
if (this.expiryTime < ((CacheItem) o).expiryTime) {
return -1;
}
if (this.expiryTime > ((CacheItem) o).expiryTime) {
return 1;
}
return 0;
}

@Override
public String toString() {
return value;
}
}

public static void main(String[] args) throws InterruptedException {
DelayQueue<CacheItem> cache = new DelayQueue<>();

// Добавление элементов в кэш
cache.put(new CacheItem("Item1", 2000)); // 2 секунды жизни
cache.put(new CacheItem("Item2", 4000)); // 4 секунды жизни

// Извлечение элементов по истечении срока жизни
while (!cache.isEmpty()) {
CacheItem item = cache.take();
System.out.println("Expired item: " + item);
}
}
}

#Java #Training #Medium #DelayQueue