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

Java使用延時隊(duì)列搞定超時訂單處理的場景

 更新時間:2022年08月16日 08:58:43   作者:趕路人兒  
這篇文章主要介紹了Java使用延時隊(duì)列搞定超時訂單處理,本文通過示例代碼給大家介紹的非常詳細(xì),對大家的學(xué)習(xí)或工作具有一定的參考借鑒價值,需要的朋友可以參考下

1、延時隊(duì)列使用場景:

那么什么時候需要用延時隊(duì)列呢?常見的延時任務(wù)場景 舉栗子:

  1. 訂單在30分鐘之內(nèi)未支付則自動取消。
  2. 重試機(jī)制實(shí)現(xiàn),把調(diào)用失敗的接口放入一個固定延時的隊(duì)列,到期后再重試。
  3. 新創(chuàng)建的店鋪,如果在十天內(nèi)都沒有上傳過商品,則自動發(fā)送消息提醒。
  4. 用戶發(fā)起退款,如果三天內(nèi)沒有得到處理則通知相關(guān)運(yùn)營人員。
  5. 預(yù)定會議后,需要在預(yù)定的時間點(diǎn)前十分鐘通知各個與會人員參加會議。
  6. 關(guān)閉空閑連接,服務(wù)器中,有很多客戶端的連接,空閑一段時間之后需要關(guān)閉之。
  7. 清理過期數(shù)據(jù)業(yè)務(wù)。比如緩存中的對象,超過了空閑時間,需要從緩存中移出。

解決方案也非常多:

  • 定期輪詢(數(shù)據(jù)庫等)
  • JDK DelayQueue
  • JDK Timer
  • ScheduledExecutorService 周期性線程池
  • 時間輪(kafka)
  • 時間輪(Netty的HashedWheelTimer)
  • Redis有序集合(zset)
  • zookeeper之curator
  • RabbitMQ
  • Quartz,xxljob等定時任務(wù)框架
  • Koala(考拉)
  • JCronTab(仿crontab的java調(diào)度器)

SchedulerX(阿里)

對于單機(jī)服務(wù)優(yōu)選DelayQueue,對于分布式環(huán)境,可以使用mq、zk、redis之類的。接下來,介紹DelayQueue的使用。

一句話介紹:DelayQueue = BlockingQueue + PriorityQueue + Delayed

2、示例:

實(shí)戰(zhàn)以訂單下單后三十分鐘內(nèi)未支付則自動取消 為業(yè)務(wù)場景,該場景的代碼邏輯分析如下:

  1. 下單后將訂單直接放入未支付的延時隊(duì)列中
  2. 如果超時未支付,則從隊(duì)列中取出,進(jìn)行修改為取消狀態(tài)的訂單
  3. 如果支付了,則不去進(jìn)行取消,或者取消的時候做個狀態(tài)篩選,即可避免更新
  4. 或者支付完成后,做個主動出隊(duì)

還有就是用戶主動取消訂單,也做個主動出隊(duì)

1)先來寫個通用的??Delayed?? :

import lombok.Getter;
import lombok.Setter;
import java.util.Date;
import java.util.concurrent.Delayed;
import java.util.concurrent.TimeUnit;

@Setter
@Getter
public class ItemDelayed<T> implements Delayed {

    /**默認(rèn)延遲30分鐘*/
    private final static long DELAY = 30 * 60 * 1000L;
    /**數(shù)據(jù)id*/
    private Long dataId;
    /**開始時間*/
    private long startTime;
    /**到期時間*/
    private long expire;
    /**創(chuàng)建時間*/
    private Date now;
    /**泛型data*/
    private T data;
    
    public ItemDelayed(Long dataId, long startTime, long secondsDelay) {
        super();
        this.dataId = dataId;
        this.startTime = startTime;
        this.expire = startTime + (secondsDelay * 1000);
        this.now = new Date();
    }

    public ItemDelayed(Long dataId, long startTime) {
        super();
        this.dataId = dataId;
        this.startTime = startTime;
        this.expire = startTime + DELAY;
        this.now = new Date();
    }

    @Override
    public int compareTo(Delayed o) {
        return (int) (this.getDelay(TimeUnit.MILLISECONDS) - o.getDelay(TimeUnit.MILLISECONDS));
    }

    @Override
    public long getDelay(TimeUnit unit) {
        return unit.convert(this.expire - System.currentTimeMillis(), TimeUnit.MILLISECONDS);
    }
}

2)再寫個通用的接口,用于規(guī)范和方便統(tǒng)一實(shí)現(xiàn) 這樣任何類型的訂單都可以實(shí)現(xiàn)這個接口 進(jìn)行延時任務(wù)的處理:

public interface DelayOrder<T> {

    /**
     * 添加延遲對象到延時隊(duì)列
     *
     * @param itemDelayed 延遲對象
     * @return boolean
     */
    boolean addToOrderDelayQueue(ItemDelayed<T> itemDelayed);

    /**
     * 根據(jù)對象添加到指定延時隊(duì)列
     *
     * @param data 數(shù)據(jù)對象
     * @return boolean
     */
    boolean addToDelayQueue(T data);

    /**
     * 移除指定的延遲對象從延時隊(duì)列中
     *
     * @param data
     */
    void removeToOrderDelayQueue(T data);
}

具體業(yè)務(wù)邏輯實(shí)現(xiàn):

@Slf4j
@Lazy(false)
@Component
public class DelayOwnOrderImpl implements DelayOrder<Order> {

    @Autowired
    private OrderService orderService;

    @Autowired
    private ExecutorService delayOrderExecutor;

    private final static DelayQueue<ItemDelayed<Order>> DELAY_QUEUE = new DelayQueue<>();

    /**
     * 初始化時加載數(shù)據(jù)庫中需處理超時的訂單
     * 系統(tǒng)啟動:掃描數(shù)據(jù)庫中未支付(要在更新時:加上已支付就不用更新了),未過期的的訂單
     */
    @PostConstruct
    public void init() {
        log.info("系統(tǒng)啟動:掃描數(shù)據(jù)庫中未支付,未過期的的訂單");
        List<Order> orderList = orderService.selectFutureOverTimeOrder();
        for (Order order : orderList) {
            ItemDelayed<Order> orderDelayed = new ItemDelayed<>(order.getId(), order.getCreateDate().getTime());
            this.addToOrderDelayQueue(orderDelayed);
        }
        log.info("系統(tǒng)啟動:掃描數(shù)據(jù)庫中未支付的訂單,總共掃描了" + orderList.size() + "個訂單,推入檢查隊(duì)列,準(zhǔn)備到期檢查...");

        /*啟動一個線程,去取延遲訂單*/
        delayOrderExecutor.execute(() -> {
            log.info("啟動處理的訂單線程:" + Thread.currentThread().getName());
            ItemDelayed<Order> orderDelayed;
            while (true) {
                try {
                    orderDelayed = DELAY_QUEUE.take();
                    //處理超時訂單
                    orderService.updateCloseOverTimeOrder(orderDelayed.getDataId());
                } catch (Exception e) {
                    log.error("執(zhí)行自營超時訂單的_延遲隊(duì)列_異常:" + e);
                }
            }
        });
    }

    /**
     * 加入延遲消息隊(duì)列
     **/
    @Override
    public boolean addToOrderDelayQueue(ItemDelayed<Order> orderDelayed) {
        return DELAY_QUEUE.add(orderDelayed);
    }

    /**
     * 加入延遲消息隊(duì)列
     **/
    @Override
    public boolean addToDelayQueue(Order order) {
        ItemDelayed<Order> orderDelayed = new ItemDelayed<>(order.getId(), order.getCreateDate().getTime());
        return DELAY_QUEUE.add(orderDelayed);
    }

    /**
     * 從延遲隊(duì)列中移除 主動取消就主動從隊(duì)列中取出
     **/
    @Override
    public void removeToOrderDelayQueue(Order order) {
        if (order == null) {
            return;
        }
        for (Iterator<ItemDelayed<Order>> iterator = DELAY_QUEUE.iterator(); iterator.hasNext(); ) {
            ItemDelayed<Order> queue = iterator.next();
            if (queue.getDataId().equals(order.getId())) {
                DELAY_QUEUE.remove(queue);
            }
        }
    }
}

分析:

  1. delayOrderExecutor是注入的一個專門處理出隊(duì)的一個線程
  2. @PostConstruct是啥呢,是在容器啟動后只進(jìn)行一次初始化動作的一個注解,相當(dāng)實(shí)用
  3. 啟動后呢,我們?nèi)?shù)據(jù)庫掃描一遍,防止有漏網(wǎng)之魚,因?yàn)閱螜C(jī)版嗎,隊(duì)列的數(shù)據(jù)是在內(nèi)存中的,重啟后肯定原先的數(shù)據(jù)會丟失,所以為保證服務(wù)質(zhì)量,我們可能會錄音.....所以為保證重啟后數(shù)據(jù)的恢復(fù),我們需要重新掃描數(shù)據(jù)庫把未支付的數(shù)據(jù)重新裝載到內(nèi)存的隊(duì)列中
  4. 接下來就是用這個線程去一直不停的訪問隊(duì)列的take()方法,當(dāng)隊(duì)列無數(shù)據(jù)就一直阻塞,或者數(shù)據(jù)沒到期繼續(xù)阻塞著,直到到期出隊(duì),然后獲取訂單的信息,去處理訂單的更新操作

到此這篇關(guān)于Java使用延時隊(duì)列搞定超時訂單處理的文章就介紹到這了,更多相關(guān)java延時隊(duì)列超時訂單處理內(nèi)容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!

相關(guān)文章

  • Mybatis實(shí)現(xiàn)聯(lián)表查詢并且分頁功能

    Mybatis實(shí)現(xiàn)聯(lián)表查詢并且分頁功能

    這篇文章主要介紹了Mybatis實(shí)現(xiàn)聯(lián)表查詢并且分頁功能,本文給大家介紹的非常詳細(xì),對大家的學(xué)習(xí)或工作具有一定的參考借鑒價值,需要的朋友可以參考下
    2021-03-03
  • Java構(gòu)造器(構(gòu)造方法)與方法區(qū)別說明

    Java構(gòu)造器(構(gòu)造方法)與方法區(qū)別說明

    這篇文章主要介紹了Java構(gòu)造器(構(gòu)造方法)與方法區(qū)別說明,具有很好的參考價值,希望對大家有所幫助。一起跟隨小編過來看看吧
    2020-09-09
  • Java截取字符串的方法

    Java截取字符串的方法

    這篇文章主要介紹了Java截取字符串的方法,實(shí)例分析了java中substring方法的使用技巧,需要的朋友可以參考下
    2015-05-05
  • Java實(shí)現(xiàn)將Object轉(zhuǎn)成List的五種方法

    Java實(shí)現(xiàn)將Object轉(zhuǎn)成List的五種方法

    在Java中,將一個Object轉(zhuǎn)換為List是一個常見的需求,尤其是在處理集合操作和數(shù)據(jù)轉(zhuǎn)換時,本文將詳細(xì)討論如何實(shí)現(xiàn)這一轉(zhuǎn)換,并提供一些代碼示例,需要的朋友可以參考下
    2025-03-03
  • SpringMVC使用@Valid注解進(jìn)行數(shù)據(jù)驗(yàn)證的方法

    SpringMVC使用@Valid注解進(jìn)行數(shù)據(jù)驗(yàn)證的方法

    本篇文章主要介紹了SpringMVC使用@Valid注解進(jìn)行數(shù)據(jù)驗(yàn)證的方法,小編覺得挺不錯的,現(xiàn)在分享給大家,也給大家做個參考。一起跟隨小編過來看看吧
    2017-02-02
  • Java 八道經(jīng)典面試題之鏈表題

    Java 八道經(jīng)典面試題之鏈表題

    本位主要介紹了Java面試中常常遇到的八道經(jīng)典鏈表問題,文中示例代碼介紹的非常詳細(xì),具有一定的參考價值,需要的小伙伴們可以學(xué)習(xí)一下
    2021-11-11
  • Java并發(fā)編程之CountDownLatch解析

    Java并發(fā)編程之CountDownLatch解析

    這篇文章主要介紹了Java并發(fā)編程之CountDownLatch解析,Sync為一個實(shí)現(xiàn)了AQS的內(nèi)部類,代理CountDownLatch的獲取和釋放操作,需要所有線程等待某個條件完成后,才執(zhí)行某個動作時,可以使用CountDownLatch,需要的朋友可以參考下
    2023-12-12
  • Java如何在命令行中獲取指定數(shù)據(jù)

    Java如何在命令行中獲取指定數(shù)據(jù)

    這篇文章主要介紹了Java如何在命令行中獲取指定數(shù)據(jù),文中通過示例代碼介紹的非常詳細(xì),對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價值,需要的朋友可以參考下
    2020-07-07
  • springboot?aop配合反射統(tǒng)一簽名驗(yàn)證實(shí)踐

    springboot?aop配合反射統(tǒng)一簽名驗(yàn)證實(shí)踐

    這篇文章主要介紹了springboot?aop配合反射統(tǒng)一簽名驗(yàn)證實(shí)踐,具有很好的參考價值,希望對大家有所幫助。如有錯誤或未考慮完全的地方,望不吝賜教
    2021-12-12
  • IDEA打包應(yīng)用程序的教程圖解

    IDEA打包應(yīng)用程序的教程圖解

    這篇文章主要介紹了IDEA打包應(yīng)用程序的教程,本文通過圖文并茂的形式給大家介紹的非常詳細(xì),對大家的學(xué)習(xí)或工作具有一定的參考借鑒價值,需要的朋友可以參考下
    2020-07-07

最新評論

新巴尔虎右旗| 斗六市| 沿河| 遵义县| 深圳市| 育儿| 巫溪县| 屯留县| 肃北| 宁波市| 安康市| 泸西县| 沁源县| 邢台县| 闽清县| 中牟县| 凭祥市| 乌鲁木齐市| 兴山县| 汾西县| 延庆县| 德惠市| 肇源县| 西吉县| 虎林市| 博湖县| 潜江市| 盘山县| 康保县| 余江县| 佛坪县| 荣成市| 贡觉县| 宝应县| 宁津县| 阿拉善右旗| 贵阳市| 芮城县| 鹤岗市| 竹溪县| 冕宁县|