Java?DelayQueue實(shí)現(xiàn)任務(wù)延時(shí)示例講解
在項(xiàng)目中有使用到延時(shí)隊(duì)列的場(chǎng)景,做個(gè)簡(jiǎn)單的記錄說明;首先DelayQueue實(shí)現(xiàn)了BlockingQueue,加入其中的元素必須實(shí)現(xiàn)Delayed接口;
當(dāng)生產(chǎn)者元素調(diào)用put往其中加入元素時(shí),出發(fā)Delayed接口的compareTo方法進(jìn)行排序,這個(gè)排序是按照時(shí)間的,按照計(jì)劃執(zhí)行的時(shí)間排序,先執(zhí)行的在前面,后執(zhí)行的排后面;消費(fèi)者獲取元素時(shí),調(diào)用getDelay方法返回的值大于0,則消費(fèi)者線程wait返回的這個(gè)時(shí)間后,再從隊(duì)列頭部取出元素;下面是個(gè)簡(jiǎn)單的例子
import org.jetbrains.annotations.NotNull;
import java.util.Date;
import java.util.concurrent.Delayed;
import java.util.concurrent.TimeUnit;
public class DelayEntity implements Delayed {
private static final Long currentTime = System.currentTimeMillis();
private String str;
private Long scheduleTime;
public DelayEntity(String str, Long delayed) {
this.str = str;
scheduleTime = System.currentTimeMillis() + (1000) * delayed;
}
@Override
public long getDelay(@NotNull TimeUnit unit) {
return unit.convert(scheduleTime - System.currentTimeMillis(), TimeUnit.MILLISECONDS);
}
@Override
public int compareTo(@NotNull Delayed o) {
return (int) (this.scheduleTime - ((DelayEntity) o).scheduleTime);
}
public String getStr() {
return str;
}
public Long getScheduleTime() {
return scheduleTime;
}
public String showScheduleTime() {
return "計(jì)劃執(zhí)行時(shí)間:" + new Date(this.scheduleTime).toString();
}
}@Test
public void test() throws InterruptedException {
DelayQueue<DelayEntity> delayQueue = new DelayQueue<>();
delayQueue.put(new DelayEntity("1", 1l));
delayQueue.put(new DelayEntity("2", 2l));
delayQueue.put(new DelayEntity("4", 3l));
while (true) {
DelayEntity take = delayQueue.take();
System.out.println("參數(shù):" + take.getStr() + ";計(jì)劃執(zhí)行時(shí)間:" + take.showScheduleTime() + ";實(shí)際執(zhí)行時(shí)間:" + new Date().toString());
}
}下面看下take方法
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);
if (delay <= 0)
return q.poll();
first = null; // don't retain ref while waiting
if (leader != null)
available.await();
else {
Thread thisThread = Thread.currentThread();
leader = thisThread;
try {
available.awaitNanos(delay);
} finally {
if (leader == thisThread)
leader = null;
}
}
}
}
} finally {
if (leader == null && q.peek() != null)
available.signal();
lock.unlock();
}
}這里可以看到,他不是一直循環(huán)的,是獲取到第一個(gè)元素的delay等待的時(shí)間,之后等待這個(gè)時(shí)間才去喚醒其他線程;
另外,添加元素時(shí),add方法和put方法都是調(diào)用的offer方法,區(qū)別是一個(gè)返回值,一個(gè)沒有;
延伸下BlockingQueue的幾個(gè)常用的操作;
1.offer方法是BlockingQueue的,offer不會(huì)阻塞執(zhí)行的方法,可以添加返回true,否則返回false;
2.BlockingQueue的put方法,如果沒有空間,會(huì)阻塞一直等到有空間
3.poll獲取元素,不會(huì)阻塞,獲取不到就返回null;
4.take,獲取不到就阻塞
到此這篇關(guān)于Java DelayQueue實(shí)現(xiàn)任務(wù)延時(shí)示例講解的文章就介紹到這了,更多相關(guān)Java DelayQueue內(nèi)容請(qǐng)搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
相關(guān)文章
java 打印一字符串,并在main()方法內(nèi)調(diào)用它
編寫一個(gè)方法(名字自定,但要符合Java編碼規(guī)范),方法內(nèi)打印一字符串,并在main()方法內(nèi)調(diào)用它。2017-02-02
mybatis interceptor 處理查詢參數(shù)及查詢結(jié)果的實(shí)例代碼
這篇文章主要介紹了mybatis interceptor 處理查詢參數(shù)及查詢結(jié)果,非常不錯(cuò),具有參考借鑒價(jià)值,需要的朋友可以參考下2017-01-01
Java Lambda表達(dá)式的方法引用和構(gòu)造器引用實(shí)例分析
這篇文章主要介紹了Java Lambda表達(dá)式的方法引用和構(gòu)造器引用,結(jié)合實(shí)例形式分析了Lambda表達(dá)式的方法引用和構(gòu)造器引用相關(guān)原理、用法及操作注意事項(xiàng),需要的朋友可以參考下2019-09-09
詳解Java中方法next()和nextLine()的區(qū)別與易錯(cuò)點(diǎn)
這篇文章主要介紹了詳解Java中方法next()和nextLine()的區(qū)別與易錯(cuò)點(diǎn),文中通過示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧2020-11-11
springboot集成CAS實(shí)現(xiàn)單點(diǎn)登錄的示例代碼
這篇文章主要介紹了springboot集成CAS實(shí)現(xiàn)單點(diǎn)登錄的示例代碼,文中通過示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧2020-06-06
Springdoc替換swagger的實(shí)現(xiàn)步驟分解
最近在spring看到的,spring要對(duì)api文檔動(dòng)手了,有些人說swagger不好用,其實(shí)也沒那么不好用,有人說代碼還是有點(diǎn)侵入性,這倒是真的,我剛試了springdoc可以說還是有侵入性但是也可以沒有侵入性,這就看你對(duì)文檔有什么要求了2023-02-02

