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

Java?DelayQueue實現延時任務的示例詳解

 更新時間:2022年08月18日 14:32:10   作者:字母哥哥  
DelayQueue是一個無界的BlockingQueue的實現類,用于放置實現了Delayed接口的對象,其中的對象只能在其到期時才能從隊列中取走。本文就來利用DelayQueue實現延時任務,感興趣的可以了解一下

一、DelayQueue的應用原理

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

BlockingQueue即阻塞隊列,java提供的面向多線程安全的隊列數據結構,當隊列內元素數量為0的時候,試圖從隊列內獲取元素的線程將被阻塞或者拋出異常。

這里的“無界”隊列,是指隊列的元素數量不存在上限,隊列的容量會隨著元素數量的增加而擴容。

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

「放入該隊列的延時任務對象,只要到達延時時間之后才能被取到」

DelayQueue 不接收null元素

「DelayQueue 只接受那些實現了java.util.concurrent.Delayed接口的對象」

二、訂單延時任務的實現

了解了DelayQueue的特點之后,我們就可以利用它來實現延時任務了,實現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);
  }

  //延時任務隊列,按照延時時間元素排序,實現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è)務的實現(訂單30分鐘不付款自動取消)。

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

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

三、訂單處理

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

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

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

@Resource
private DelayQueue<OrderDelayObject> orderDelayQueue;

//發(fā)起訂單下單的時候將訂單演示對象放入orderDelayQueue
orderDelayQueue.add(
        new OrderDelayObject(
                "訂單延時取消任務",
                30 * 60 * 1000,    //延時30分鐘
                "延時任務訂單對象信息"
        )
);

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

@Component
public class DelayObjectConsumer  implements InitializingBean {

  @Resource
  private DelayQueue<OrderDelayObject> orderDelayQueue;

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

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

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

四、優(yōu)缺點

使用DelayQueue實現延時任務非常簡單,而且簡便,全部都是標準的JDK代碼實現,不用引入第三方依賴(不依賴redis實現、消息隊列實現等),非常的輕量級。

它的缺點就是所有的操作都是基于應用內存的,一旦出現應用單點故障,可能會造成延時任務數據的丟失。如果訂單并發(fā)量非常大,因為DelayQueue是無界的,訂單量越大,隊列內的對象就越多,可能造成OOM的風險。所以使用DelayQueue實現延時任務,只適用于任務量較小的情況。

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

您可能感興趣的文章:

相關文章

最新評論

灌云县| 阳春市| 临夏市| 藁城市| 崇文区| 重庆市| 肇州县| 陵川县| 竹溪县| 罗江县| 铜川市| 呼图壁县| 德安县| 仁怀市| 延安市| 甘德县| 手机| 河津市| 沿河| 高陵县| 宜宾县| 波密县| 乃东县| 天峨县| 封丘县| 江源县| 行唐县| 柞水县| 靖西县| 休宁县| 澜沧| 乐业县| 岳西县| 玉田县| 佛教| 甘孜县| 祁门县| 叶城县| 铅山县| 隆尧县| 聂拉木县|