Очереди с задержкой - это потокобезопасные структуры данных, элементы которых можно извлекать после заданной задержки.

1- Как использовать очередь задержки?

В отличие от любых других очередей, очередь задержки принимает объекты классов, которые реализуют интерфейс Delayed, который также расширяет интерфейс Comparable, который вы можете увидеть ниже.

public interface Delayed extends Comparable<Delayed> {
    long getDelay(TimeUnit unit);
}
public interface Comparable<T> {
    public int compareTo(T o);
}

Итак, когда вы создаете свой собственный объект, который будет помещен в отложенную очередь, вы реализуете эти методы. Давайте создадим наш собственный класс Delayed.

public class DelayedItem implements Delayed {
    private String name;
    private long startingTime;

    public DelayedItem(String name, long delay) {
        this.name = name;
        this.startingTime = System.currentTimeMillis() + delay;
    }

    public String getName() {
        return name;
    }

    @Override
    public long getDelay(TimeUnit unit) {
        long delay = startingTime - System.currentTimeMillis();
        return unit.toMillis(delay);
    }

    @Override
    public int compareTo(Delayed o) {
        return Long.compare(startingTime, ((DelayedItem) o).startingTime);
    }
}

В приведенном выше примере мы берем два параметра для инициализации объекта с задержкой. Первое - это имя, оно предназначено только для демонстрации и будет использоваться позже. Второй - задержка, после которой мы можем получить объект из очереди. Как вы заметили, мы создали поле startTime, используя заданную задержку и текущее время. В этом поле указано, что по истечении этого времени вы можете удалить этот объект из очереди. Затем мы реализовали методы getDelay и compareTo. getDelay просто возвращает задержку, как следует из его названия, а compareTo выполняет сравнение для сортировки объектов в очереди в соответствии с их временем, когда они могут быть удалены.

Теперь пришло время использовать наш отложенный элемент и очередь задержки.

public static void main(String[] args) {
    DelayQueue<DelayedItem> delayedItems = new DelayQueue<>();
    DelayedItem delayedItem1 = new DelayedItem("item1", 1000);
    DelayedItem delayedItem2 = new DelayedItem("item2", 500);
    DelayedItem delayedItem3 = new DelayedItem("item3", 750);
    DelayedItem delayedItem4 = new DelayedItem("item3", 1250);

    delayedItems.add(delayedItem1);
    delayedItems.add(delayedItem2);
    delayedItems.add(delayedItem3);
    delayedItems.add(delayedItem4);

    while (!delayedItems.isEmpty()) {
        try {
            System.out.println(delayedItems.take().getName());
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
    }
}

Сначала мы создаем несколько элементов, каждый из которых имеет разные задержки, а затем помещаем их в очередь. Затем мы извлекаем элементы из очереди и выводим их имена в консоль. Выход будет

item2
item3
item1
item3

Как видите, item2 помещается в очередь как третий, но поскольку у него самая низкая задержка среди других элементов, он снимается первым, а остальные выстраиваются в очередь в соответствии с их задержками.

2- Когда использовать очередь задержки?

Очереди с задержкой могут использоваться где угодно в соответствии с потребностями, и они легко адаптируются к многопоточным средам, поскольку это потокобезопасная структура данных.

В этом руководстве я рассказал об очередях задержки и о том, как их использовать. Я надеюсь, тебе это нравится.