DelayQueue 延時隊列,延時一段時間後執行的隊列,根據這個特性,可以應用在
1 緩存的生成及自動過期刪除
2 任務超時處理
…
其存儲元素必須繼承實現Delayed接口
public interface Delayed extends Comparable<Delayed> {
long getDelay(TimeUnit unit);
}
可見 我們需要實現兩個方法
1 getDelay 獲取延遲時間
2 compareTo 內部隊列的排序
我們先來看下 入隊、出隊
public boolean add(E e) {
return offer(e);
}
public void put(E e) {
offer(e);
}
public boolean offer(E e) {
// 兩個作用
//1 下面的引用不需要通過this.lock,直接從堆棧獲取引用 效率更高
//2 防止誤操作
final ReentrantLock lock = this.lock;
//獨佔鎖 線程安全
lock.lock();
try {
//這裏的q是PriorityQueue 優先隊列 fifo模式 可以看出DelayQueue 使用的是先進先出的模式,將對象放入隊列中 這裏會調用compareTo進行內部排序
q.offer(e);
//獲取當前隊列最頂隊列對象,如果和當前對象相等,說明
//原先隊列爲空
if (q.peek() == e) {
leader = null;
//插入成功,通知喚醒
available.signal();
}
return true;
} finally {
// 釋放鎖
lock.unlock();
}
}
//排序方法
private void siftUpComparable(int k, E x) {
Comparable<? super E> key = (Comparable<? super E>) x;
//循環比較,找到比自己大的 break
while (k > 0) {
int parent = (k - 1) >>> 1;
Object e = queue[parent];
if (key.compareTo((E) e) >= 0)
break;
queue[k] = e;
k = parent;
}
queue[k] = key;
}
主要看的還是offer方法
//
public E peek() {
final ReentrantLock lock = this.lock;
lock.lock();
try {
return q.peek();
} finally {
lock.unlock();
}
}
public E poll() {
final ReentrantLock lock = this.lock;
lock.lock();
try {
E first = q.peek();
//如果還未過期 則返回null
if (first == null || first.getDelay(NANOSECONDS) > 0)
return null;
else//
return q.poll();
} finally {
lock.unlock();
}
}
public E take() throws InterruptedException {
final ReentrantLock lock = this.lock;
//獨佔鎖,可被打斷,拋出異常
lock.lockInterruptibly();
try {
//循環執行
for (;;) {
//獲取當前首個對象
E first = q.peek();
//如果爲空 說明隊列爲空,則進行等待 直到有對象入隊喚醒
if (first == null)
available.await();
else {
//獲取需要等待時間 微妙單位
long delay = first.getDelay(NANOSECONDS);
//如果小於0,已經過時,直接拋出對象返回
if (delay <= 0)
return q.poll();
//對象回收
first = null; // don't retain ref while waiting
//如果當前leader已經被某線程賦值,則等待
if (leader != null)
available.await();
else {
Thread thisThread = Thread.currentThread();
//否則賦值leader
leader = thisThread;
try {
//等待delay時間後 喚醒 繼續循環
available.awaitNanos(delay);
} finally {
//leader=null
if (leader == thisThread)
leader = null;
}
}
}
}
} finally {
//當隊列不爲空,則進行通知,否則不通知
if (leader == null && q.peek() != null)
available.signal();
lock.unlock();
}
}
//he
public E poll(long timeout, TimeUnit unit) throws InterruptedException {
long nanos = unit.toNanos(timeout);
final ReentrantLock lock = this.lock;
lock.lockInterruptibly();
try {
for (;;) {
E first = q.peek();
if (first == null) {
if (nanos <= 0)
return null;
else
nanos = available.awaitNanos(nanos);
} else {
long delay = first.getDelay(NANOSECONDS);
if (delay <= 0)
return q.poll();
if (nanos <= 0)
return null;
first = null; // don't retain ref while waiting
if (nanos < delay || leader != null)
nanos = available.awaitNanos(nanos);
else {
Thread thisThread = Thread.currentThread();
leader = thisThread;
try {
long timeLeft = available.awaitNanos(delay);
nanos -= delay - timeLeft;
} finally {
if (leader == thisThread)
leader = null;
}
}
}
}
} finally {
if (leader == null && q.peek() != null)
available.signal();
lock.unlock();
}
}
tack 方法貌似多點,不過整過過程還是比較簡單的!
1 循環
2 判斷是否過時
3 等待
public final long awaitNanos(long nanosTimeout)
throws InterruptedException {
//線程是否被打斷 打斷 則拋異常,這裏和lock.lockInterruptibly();對應
if (Thread.interrupted())
throw new InterruptedException();
//通過當前線程 創建節點
Node node = addConditionWaiter();
//嘗試是否,並且獲取當前狀態
int savedState = fullyRelease(node);
//過期時間
final long deadline = System.nanoTime() + nanosTimeout;
int interruptMode = 0;
//判斷是否需要等待
while (!isOnSyncQueue(node)) {
if (nanosTimeout <= 0L) {
//插到隊列末尾
transferAfterCancelledWait(node);
break;
}
if (nanosTimeout >= spinForTimeoutThreshold)
//調用底層 對該線程進行阻塞
LockSupport.parkNanos(this, nanosTimeout);
//是否打斷
if ((interruptMode = checkInterruptWhileWaiting(node)) != 0)
break;
nanosTimeout = deadline - System.nanoTime();
}
if (acquireQueued(node, savedState) && interruptMode != THROW_IE)
interruptMode = REINTERRUPT;
if (node.nextWaiter != null)
unlinkCancelledWaiters();
if (interruptMode != 0)
reportInterruptAfterWait(interruptMode);
return deadline - System.nanoTime();
}
總結
適用於一段時間後執行的場景,常見於自定義緩存、超時、某段時間後需要處理的業務。