Maison  >  Article  >  Java  >  Comment utiliser la file d'attente différée DelayQueue dans la file d'attente du pool de threads Java

Comment utiliser la file d'attente différée DelayQueue dans la file d'attente du pool de threads Java

WBOY
WBOYavant
2023-04-14 21:22:011196parcourir

Dans la file d'attente de blocage, en plus d'ajouter et de supprimer des éléments, nous pouvons retarder la suppression des éléments, c'est-à-dire en utilisant la méthode DelayQueue. Cet article vous parlera de DelayQueue dans la file d'attente du pool de threads Java - Delay Queue

public enum QueueTypeEnum {
    ARRAY_BLOCKING_QUEUE(1, "ArrayBlockingQueue"),
    LINKED_BLOCKING_QUEUE(2, "LinkedBlockingQueue"),
    DELAY_QUEUE(3, "DelayQueue"),
    PRIORITY_BLOCKING_QUEUE(4, "PriorityBlockingQueue"),
    SYNCHRONOUS_QUEUE(5, "SynchronousQueue"),
    LINKED_TRANSFER_QUEUE(6, "LinkedTransferQueue"),
    LINKED_BLOCKING_DEQUE(7, "LinkedBlockingDeque"),
    VARIABLE_LINKED_BLOCKING_QUEUE(8, "VariableLinkedBlockingQueue"),
    MEMORY_SAFE_LINKED_BLOCKING_QUEUE(9, "MemorySafeLinkedBlockingQueue");
}

DelayQueue Delay Queue

est similaire à PriorityBlockingQueue, qui est une File d'attente de blocage de priorité illimitée implémentée par le tas binaire. Tous les éléments sont requis pour implémenter l'interface Delayed, et les tâches sont extraites de la file d'attente en exécutant delay. Les éléments ne peuvent être extraits de la file d'attente qu'après l'expiration du délai. Les paramètres génériques de DelayQueue doivent implémenter l'interface Delayed. L'interface Delayed hérite de l'Interface comparable utilise en interne une file d'attente prioritaire non thread-safe (PriorityQueue) et utilise le mode Leader/Followers pour minimiser le temps d'attente inutile. DelayQueue n'est pas autorisé à contenir des éléments null.

public interface Delayed extends Comparable<Delayed> {

    /**
     * 返回与此对象关联的剩余延迟(给定的时间单位)。
     * @param unit 时间单位
     * @返回剩余延迟;零值或负值表示 延迟已过期
     */
    long getDelay(TimeUnit unit);
}

Scénarios d'utilisation de DelayQueue

Conception du système de cache : DelayQueue peut être utilisé pour enregistrer la période de validité des éléments de cache, et un thread peut être utilisé pour interroger le DelayQueue dans une boucle une fois que l'élément peut être obtenu à partir du DelayQueue. , cela signifie que la période de validité du cache a expiré.

Planification des tâches chronométrées : utilisez DelayQueue pour enregistrer les tâches et le temps d'exécution qui seront exécutés ce jour-là. Une fois la tâche obtenue de DelayQueue, elle sera exécutée. Par exemple, TimerQueue est implémenté à l'aide de DelayQueue.

Attribut DelayQueue

//可重入同步锁
private final transient ReentrantLock lock = new ReentrantLock();

//DelayQueue的实现依赖于PriorityQueue(优先队列)
private final PriorityQueue<E> q = new PriorityQueue<E>();

//第一个等待某个延时对象的线程,在延时对象还没有到期时其他线程看到这个leader不为null,那么就直接wait
//主要是为了避免大量线程在同一时间点唤醒,导致大量的竞争,反而影响性能
private Thread leader = null;

//条件队列,用于wait线程
private final Condition available = lock.newCondition();

Méthode de construction de DelayQueue

//从上面属性就可以看出,DelayQueue采用了饿汉模式,调用构造方法即创建了队列实例
public DelayQueue() {}

/**
 * 创建一个DelayQueue,最初包含给定的Collection实例集合。
 * @param c 最初包含的元素集合
 */
public DelayQueue(Collection<? extends E> c) {
    this.addAll(c);
}

implémentation de l'exemple d'utilisation de l'interface retardée

class MyDelay<T> implements Delayed {

    long delayTime; // 延迟时间
    long expire; // 过期时间
    T data;

    public MyDelay(long delayTime, T t) {
        this.delayTime = delayTime;
        // 过期时间 = 当前时间 + 延迟时间
        this.expire = System.currentTimeMillis() + delayTime;
        data = t;
    }

    /**
     * 剩余时间 = 到期时间 - 当前时间
     */
    @Override
    public long getDelay(TimeUnit unit) {
        return unit.convert(this.expire - System.currentTimeMillis(), TimeUnit.MILLISECONDS);
    }

    /**
     * 优先级规则:两个任务比较,时间短的优先执行
     */
    @Override
    public int compareTo(Delayed o) {
        long f = this.getDelay(TimeUnit.MILLISECONDS) - o.getDelay(TimeUnit.MILLISECONDS);
        return (int) f;
    }


    @Override
    public String toString() {
        return "delayTime=" + delayTime +
                ", expire=" + expire +
                ", data=" + data;
    }
}

public class DelayQueueDemo {
    static BlockingQueue<Delayed> queue = new DelayQueue();
    public static void main(String[] args) throws InterruptedException {
        queue.add(new MyDelay(8, "第一次添加任务"));
        queue.add(new MyDelay(3, "第二次添加任务"));
        queue.add(new MyDelay(5, "第三次添加任务"));

        while (!queue.isEmpty()) {
            Delayed delayed = queue.take();
            System.out.println(delayed);
        }
    }
}

Résumé de DelayQueue

DelayQueue adopte en fait le mode décorateur et ajoute élément d'acquisition de temps de retard sous l'emballage de PriorityQue ue La fonction, ses principales fonctionnalités sont résumées comme suit :

  • DelayQueue est une file d'attente de blocage illimitée, qui est implémentée en interne à l'aide de PriorityQueue

  • Les éléments entrant dans la file d'attente doivent implémenter l'interface Delayed Lors de la création d'un élément, vous pouvez spécifier sa durée. prend pour être supprimé de la file d'attente. Obtenez l'élément actuel, qui ne peut être extrait qu'à l'expiration du délai

  • La tête de la file d'attente est l'élément retardé qui a la durée de stockage la plus longue après l'expiration du délai

  • Si il n'y a pas d'élément retardé non expiré, et la file d'attente n'a pas de tête, et le sondage renverra null

  • Lorsque la méthode getDelay (TimeUnit.NANOSECONDS) d'un élément renvoie une valeur inférieure ou égale à 0, cela signifie que l'élément a expiré

  • Les éléments non expirés ne peuvent pas être supprimés à l'aide d'éléments poll ou take, ces éléments ne seront pas traités comme des éléments normaux ; par exemple : la méthode size renvoie la somme des nombres d'éléments expirés et non expirés

  • Cette file d'attente n'autorise pas les éléments nuls

Ce qui précède est le contenu détaillé de. pour plus d'informations, suivez d'autres articles connexes sur le site Web de PHP en chinois!

Déclaration:
Cet article est reproduit dans:. en cas de violation, veuillez contacter admin@php.cn Supprimer