>  기사  >  Java  >  Java 스레드 풀 대기열에서 지연 대기열 DelayQueue를 사용하는 방법

Java 스레드 풀 대기열에서 지연 대기열 DelayQueue를 사용하는 방법

WBOY
WBOY앞으로
2023-04-14 21:22:011127검색

차단 대기열에서는 요소 추가 및 삭제 외에도 DelayQueue 메서드를 사용하여 요소 삭제를 지연할 수 있습니다. 이 기사에서는 Java 스레드 풀 큐의 DelayQueue에 대해 설명합니다. 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

는 바이너리 힙으로 구현된 Unbounded Priority Blocking Queue인 PriorityBlockingQueue와 유사합니다. 모든 요소는 Delayed 인터페이스를 구현하는 데 필요하며 delay를 실행하면 작업이 대기열에서 추출됩니다. 요소는 지연이 만료된 후에만 대기열에서 추출할 수 있습니다. DelayQueue의 일반 매개변수는 Delayed 인터페이스를 구현해야 합니다. Delayed 인터페이스는 Comparable 인터페이스를 상속합니다. DelayQueue는 내부적으로 스레드로부터 안전하지 않은 우선순위 대기열(PriorityQueue)을 사용하고 불필요한 대기 시간을 최소화하기 위해 Leader/Followers 모드를 사용합니다. DelayQueue에는 null 요소가 포함될 수 없습니다.

public interface Delayed extends Comparable<Delayed> {

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

DelayQueue 사용 시나리오

캐시 시스템 설계: DelayQueue는 캐시 요소의 유효 기간을 저장하는 데 사용할 수 있으며 스레드는 DelayQueue에서 요소를 얻을 수 있으면 루프에서 DelayQueue를 쿼리하는 데 사용할 수 있습니다. , 이는 캐시 유효 기간이 만료되었음을 의미합니다.

Timed 작업 예약: 해당 날짜에 실행될 작업과 실행 시간을 저장하려면 DelayQueue를 사용하세요. DelayQueue에서 작업을 가져오면 TimerQueue가 실행됩니다.

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();

DelayQueue 구성 방법

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

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

Delayed 인터페이스 구현 예시

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);
        }
    }
}

DelayQueue 요약

DelayQueue는 실제로 데코레이터 모드를 채택하고 PriorityQueue 패키징 아래에 지연 시간 획득 요소를 추가합니다. 주요 기능은 다음과 같이 요약됩니다.

  • DelayQueue는 PriorityQueue를 사용하여 내부적으로 구현되는 무제한 차단 큐입니다.

  • 큐에 들어가는 요소는 요소를 생성할 때 지연된 인터페이스를 구현해야 합니다. 지연이 만료될 때만 추출할 수 있는 현재 요소를 가져옵니다

  • 큐의 헤드는 지연이 만료된 후 저장 시간이 가장 긴 지연된 요소입니다

  • If 만료되지 않은 지연된 요소가 없고 대기열에 head가 없으며 폴링은 null을 반환합니다

  • 요소의 getDelay(TimeUnit.NANOSECONDS) 메서드가 0보다 작거나 같은 값을 반환하면 요소가 만료되었습니다

  • 만료되지 않은 항목은 poll 또는 take 요소를 사용하여 제거할 수 없습니다. 이러한 요소는 일반 요소로 처리되지 않습니다. 예를 들어 size 메소드는 만료된 요소와 만료되지 않은 요소의 개수 합계를 반환합니다.

  • 이 대기열 null 요소는 허용되지 않습니다

위 내용은 Java 스레드 풀 대기열에서 지연 대기열 DelayQueue를 사용하는 방법의 상세 내용입니다. 자세한 내용은 PHP 중국어 웹사이트의 기타 관련 기사를 참조하세요!

성명:
이 기사는 yisu.com에서 복제됩니다. 침해가 있는 경우 admin@php.cn으로 문의하시기 바랍니다. 삭제