1、DelayQueue簡介
DelayQueue 也是 Java 并發包(java.util.concurrent)中的一個特殊隊列,用于在指定的延遲時間之后處理元素。
DelayQueue的一些關鍵特性:
延遲元素處理:只有當元素的延遲時間到期時,元素才能被取出。使用 take 方法會阻塞直到有元素到期。
無界隊列:DelayQueue 是一個無界隊列,這意味著它可以包含任意數量的元素(太多可能內存溢出)。
元素排序:DelayQueue 中的元素按到期時間排序,最先到期的元素最早被取出。
阻塞操作:take 方法會阻塞直到有元素到期,而 poll 方法可以在指定的時間內等待。
2、DelayQueue適用場景
DelayQueue 通常用于需要在未來某個時間點執行任務的場景。
定時任務調度:可以用于實現定時任務調度系統,任務在特定的時間點被執行。
緩存過期:實現緩存系統中的過期機制,當緩存項的過期時間到達時,將其從緩存中移除。
限流控制:在某些系統中用于限流,限制某一操作在指定時間段內的執行頻率。
3.DelayQueue 常見使用場景示例
我們這里希望任務可以按照我們預期的時間執行,例如提交 3 個任務,分別要求 1s、2s、3s 后執行,即使是亂序添加,1s 后要求 1s 執行的任務會準時執行。
對此我們可以使用 DelayQueue 來實現,所以我們首先需要繼承 Delayed 實現 DelayedTask,實現 getDelay 方法以及優先級比較 compareTo。
import lombok.Data;import java.time.Duration;
import java.util.concurrent.DelayQueue;
import java.util.concurrent.Delayed;
import java.util.concurrent.TimeUnit;/*** 延遲任務*/
@Data
public class DelayedTask<D> implements Delayed {/*** 任務到期時間*/private long deadlineNanos;/*** 待處理數據*/private D data;public DelayedTask(Duration delayTime, D data) {this.deadlineNanos = System.nanoTime() + delayTime.toNanos();this.data = data;}/*** 查看當前任務還有多久到期** @param unit 時間單位* @return 到期時間*/@Overridepublic long getDelay(TimeUnit unit) {return unit.convert(Math.max(0, deadlineNanos - System.nanoTime()), TimeUnit.NANOSECONDS);}/*** 延遲隊列需要到期時間升序入隊,所以我們需要實現compareTo進行到期時間比較** @param o 延遲任務* @return 比較大小*/@Overridepublic int compareTo(Delayed o) {long l = getDelay(TimeUnit.NANOSECONDS) - o.getDelay(TimeUnit.NANOSECONDS);if (l > 0) {return 1;} else if (l < 0) {return -1;} else {return 0;}}/*** 輸出數據*/public void execute() {System.out.println(data);}}
使用:?
// 創建延遲隊列,并添加任務
DelayQueue<DelayedTask<String>> delayQueue = new DelayQueue<>();
//分別添加1s、2s、3s到期的任務
delayQueue.add(new DelayedTask<>(Duration.ofSeconds(2), "Task 2"));
delayQueue.add(new DelayedTask<>(Duration.ofSeconds(1), "Task 1"));
delayQueue.add(new DelayedTask<>(Duration.ofSeconds(3), "Task 3"));
// 取出任務并執行
while (!delayQueue.isEmpty()) {//阻塞獲取最先到期的任務DelayedTask<String> task = delayQueue.take();task.execute();
}
4.DelayQueue的源碼解析
見《DelayQueue詳解-CSDN博客》