最新国产好看的视频,伊人天堂AV在线,国产Aaaaaa视频,蜜臀视频在线观看一区,人妻av色图,密臀久久久精品影片,青青视频免费观看毛片,久草在线观看视,国产三级精品色情在线

java通過DelayQueue實現(xiàn)延時任務

 更新時間:2023年07月24日 08:34:11   作者:字母哥哥  
本文主要介紹了java通過DelayQueue實現(xiàn)延時任務,文中通過示例代碼介紹的非常詳細,對大家的學習或者工作具有一定的參考學習價值,需要的朋友們下面隨著小編來一起學習學習吧

實現(xiàn)延時任務有很多的方法,網(wǎng)上關于延時任務的實現(xiàn)的文章已經(jīng)不少了。比如:實現(xiàn)延時任務的10種方法等等。但是這些文章基本上都是將方法大概的列舉一下,給出部分示例代碼,對于有經(jīng)驗的老程序員可能一看就知道該怎么去把它實現(xiàn)完整,但是對于初學者來說不夠友好。

小概念:什么是延時任務?舉個例子:你買了一張火車票,必須在30分鐘之內(nèi)付款,否則該訂單被自動取消?!赣唵?0分鐘不付款自動取消,這個任務就是一個延時任務?!?/p>

一、DelayQueue的應用原理

DelayQueue是一個無界的BlockingQueue的實現(xiàn)類,用于放置實現(xiàn)了Delayed接口的對象,其中的對象只能在其到期時才能從隊列中取走。

  • BlockingQueue即阻塞隊列,java提供的面向多線程安全的隊列數(shù)據(jù)結(jié)構(gòu),當隊列內(nèi)元素數(shù)量為0的時候,試圖從隊列內(nèi)獲取元素的線程將被阻塞或者拋出異常。
  • 這里的“無界”隊列,是指隊列的元素數(shù)量不存在上限,隊列的容量會隨著元素數(shù)量的增加而擴容。

DelayQueue實現(xiàn)了BlockingQueue接口,所以具有無界、阻塞的特點,除此之外它自己的核心特點就是:

  • 「放入該隊列的延時任務對象,只要到達延時時間之后才能被取到」。
  • DelayQueue 不接收null元素
  • 「DelayQueue 只接受那些實現(xiàn)了java.util.concurrent.Delayed接口的對象」

二、訂單延時任務的實現(xiàn)

了解了DelayQueue的特點之后,我們就可以利用它來實現(xiàn)延時任務了,實現(xiàn)java.util.concurrent.Delayed接口。

import?org.jetbrains.annotations.NotNull;
import?java.text.SimpleDateFormat;
import?java.util.Date;
import?java.util.concurrent.Delayed;
import?java.util.concurrent.TimeUnit;
/**
?*?延時訂單任務
?*/
public?class?OrderDelayObject?implements?Delayed?{
??private?String?name;
??private?long?delayTime;???//延時時間
??//實際業(yè)務中這里傳訂單信息對象,我這里只做demo,所以使用字符串了
??private?String?order;
??public?OrderDelayObject(String?name,?long?delayTime,?String?order)?{
????this.name?=?name;
????//延時時間加上當前時間
????this.delayTime?=?System.currentTimeMillis()?+?delayTime;
????this.order?=?order;
??}
??//獲取延時任務的倒計時時間
??@Override
??public?long?getDelay(TimeUnit?unit)?{
????long?diff?=?delayTime?-?System.currentTimeMillis();
????return?unit.convert(diff,?TimeUnit.MILLISECONDS);
??}
??//延時任務隊列,按照延時時間元素排序,實現(xiàn)Comparable接口
??@Override
??public?int?compareTo(@NotNull?Delayed?obj)?{
????return?Long.compare(this.delayTime,?((OrderDelayObject)?obj).delayTime);
??}
??@Override
??public?String?toString()?{
????Date?date?=?new?Date(delayTime);
????SimpleDateFormat?sd?=?new?SimpleDateFormat("yyyy-MM-dd?HH:mm:ss");
????return?"\nOrderDelayObject:{"
????????????+?"name="?+?name
????????????+?",?time="?+?sd.format(date)
????????????+?",?order="?+?order
????????????+?"}";
??}
}?

上文類中的order為訂單信息對象,在實際的業(yè)務開發(fā)過程中應該是傳遞訂單信息,用于取消訂單業(yè)務的實現(xiàn)(訂單30分鐘不付款自動取消)。

Delayed接口繼承自 Comparable接口,所以需要實現(xiàn)compareTo方法,用于延時任務在隊列中按照“延時時間”進行排序。

getDelay方法是Delayed接口方法,實現(xiàn)該方法提供獲取延時任務的倒計時時間

三、訂單處理

首先我們需要一個容器,永久保存延時任務隊列,如果是Spring開發(fā)環(huán)境我們可以這樣做。

@Bean("orderDelayQueue")
public DelayQueue<OrderDelayObject> orderDelayQueue(){
    return new DelayQueue<OrderDelayObject>();
}

當用戶下單的時候,將訂單下單任務放入延時隊列

@Resource
private?DelayQueue<OrderDelayObject>?orderDelayQueue;
//發(fā)起訂單下單的時候?qū)⒂唵窝菔緦ο蠓湃雘rderDelayQueue
orderDelayQueue.add(
????????new?OrderDelayObject(
????????????????"訂單延時取消任務",
????????????????30?*?60?*?1000,????//延時30分鐘
????????????????"延時任務訂單對象信息"
????????)
);

系統(tǒng)內(nèi)開啟一個線程,不斷的從隊列中獲取消息,獲取到之后對延時消息進行處理。DelayQueue的take方法從隊列中獲取延時任務對象,如果隊列元素數(shù)量為0,或者沒有到達“延時時間的任務”,該線程會被阻塞。

@Component
public class DelayObjectConsumer<OrderDelayObject> implements InitializingBean {
? @Resource
? private DelayQueue<OrderDelayObject> orderDelayQueue;
? @Override
? public void afterPropertiesSet() throws Exception {
? ? new Thread(() -> {
? ? ? while (true) {
? ? ? ? OrderDelayObject task = orderDelayQueue.take();
? ? ? ? System.out.println(task.toString());
? ? ? ? System.out.println(task.getOrder());
? ? ? ? //根據(jù)order訂單信息,去查詢該訂單的支付信息
? ? ? ? //如果用戶沒有進行支付,將訂單從數(shù)據(jù)庫中關閉
? ? ? ? //如果訂單并發(fā)量比較大,這里可以考慮異步或線程池的方式進行處理
? ? ? }
? ? }).start();
? }
}

需要說明的是,這里的while-true循環(huán)的延時任務處理是順序執(zhí)行的,在訂單并發(fā)量比較大的時候,需要考慮異步處理的方式完成訂單的關閉操作。我之前寫過一個SpringBoot的可觀測、易配置的線程池開源項目,可能會對你有幫助,源代碼地址:gitee.com/hanxt/zimug-monitor-threadpool

經(jīng)過我的測試,放入orderDelayQueue的延時任務,在半小時之后得到正確的執(zhí)行處理。說明我們的實現(xiàn)是正確的。

四、優(yōu)缺點

  • 使用DelayQueue實現(xiàn)延時任務非常簡單,而且簡便,全部都是標準的JDK代碼實現(xiàn),不用引入第三方依賴(不依賴redis實現(xiàn)、消息隊列實現(xiàn)等),非常的輕量級。
  • 它的缺點就是所有的操作都是基于應用內(nèi)存的,一旦出現(xiàn)應用單點故障,可能會造成延時任務數(shù)據(jù)的丟失。如果訂單并發(fā)量非常大,因為DelayQueue是無界的,訂單量越大,隊列內(nèi)的對象就越多,可能造成OOM的風險。所以使用DelayQueue實現(xiàn)延時任務,只適用于任務量較小的情況。

到此這篇關于java通過DelayQueue實現(xiàn)延時任務的文章就介紹到這了,更多相關java DelayQueue延時任務內(nèi)容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關文章希望大家以后多多支持腳本之家!

相關文章

最新評論

垫江县| 福泉市| 舟曲县| 东丽区| 浦北县| 同德县| 张北县| 榆林市| 襄樊市| 崇义县| 伽师县| 东明县| 临漳县| 上高县| 丰宁| 宝兴县| 平顶山市| 曲周县| 深水埗区| 鹤壁市| 鹰潭市| 定西市| 阜新市| 惠州市| 临洮县| 通江县| 左云县| 连山| 奉节县| 东源县| 河池市| 玉溪市| 岳普湖县| 太康县| 漳浦县| 葫芦岛市| 兴城市| 瑞安市| 东阿县| 鄄城县| 湛江市|