차단 대기열에서는 요소 추가 및 삭제 외에도 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"); }
는 바이너리 힙으로 구현된 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를 쿼리하는 데 사용할 수 있습니다. , 이는 캐시 유효 기간이 만료되었음을 의미합니다.
Timed 작업 예약: 해당 날짜에 실행될 작업과 실행 시간을 저장하려면 DelayQueue를 사용하세요. DelayQueue에서 작업을 가져오면 TimerQueue가 실행됩니다.
//可重入同步锁 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采用了饿汉模式,调用构造方法即创建了队列实例 public DelayQueue() {} /** * 创建一个DelayQueue,最初包含给定的Collection实例集合。 * @param c 最初包含的元素集合 */ public DelayQueue(Collection<? extends E> c) { this.addAll(c); }
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는 실제로 데코레이터 모드를 채택하고 PriorityQueue 패키징 아래에 지연 시간 획득 요소를 추가합니다. 주요 기능은 다음과 같이 요약됩니다.
DelayQueue는 PriorityQueue를 사용하여 내부적으로 구현되는 무제한 차단 큐입니다.
큐에 들어가는 요소는 요소를 생성할 때 지연된 인터페이스를 구현해야 합니다. 지연이 만료될 때만 추출할 수 있는 현재 요소를 가져옵니다
큐의 헤드는 지연이 만료된 후 저장 시간이 가장 긴 지연된 요소입니다
If 만료되지 않은 지연된 요소가 없고 대기열에 head가 없으며 폴링은 null을 반환합니다
요소의 getDelay(TimeUnit.NANOSECONDS) 메서드가 0보다 작거나 같은 값을 반환하면 요소가 만료되었습니다
만료되지 않은 항목은 poll 또는 take 요소를 사용하여 제거할 수 없습니다. 이러한 요소는 일반 요소로 처리되지 않습니다. 예를 들어 size 메소드는 만료된 요소와 만료되지 않은 요소의 개수 합계를 반환합니다.
이 대기열 null 요소는 허용되지 않습니다
위 내용은 Java 스레드 풀 대기열에서 지연 대기열 DelayQueue를 사용하는 방법의 상세 내용입니다. 자세한 내용은 PHP 중국어 웹사이트의 기타 관련 기사를 참조하세요!