<output id="qn6qe"></output>

    1. <output id="qn6qe"><tt id="qn6qe"></tt></output>
    2. <strike id="qn6qe"></strike>

      亚洲 日本 欧洲 欧美 视频,日韩中文字幕有码av,一本一道av中文字幕无码,国产线播放免费人成视频播放,人妻少妇偷人无码视频,日夜啪啪一区二区三区,国产尤物精品自在拍视频首页,久热这里只有精品12

      完整實現-通過DelayQueue實現延時任務

      實現延時任務有很多的方法,網上關于延時任務的實現的文章已經不少了。比如:實現延時任務的10種方法等等。但是這些文章基本上都是將方法大概的列舉一下,給出部分示例代碼,對于有經驗的老程序員可能一看就知道該怎么去把它實現完整,但是對于初學者來說不夠友好。所以,我打算寫一個系列的文章,詳細的給出每種延時任務的實現方法、完整實現代碼,以及工作原理,歡迎并期待大家關注我

      小概念:什么是延時任務?舉個例子:你買了一張火車票,必須在30分鐘之內付款,否則該訂單被自動取消。訂單30分鐘不付款自動取消,這個任務就是一個延時任務。

      一、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;   //延時時間
        //實際業務中這里傳訂單信息對象,我這里只做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為訂單信息對象,在實際的業務開發過程中應該是傳遞訂單信息,用于取消訂單業務的實現(訂單30分鐘不付款自動取消)。
      • Delayed接口繼承自 Comparable接口,所以需要實現compareTo方法,用于延時任務在隊列中按照“延時時間”進行排序。
      • getDelay方法是Delayed接口方法,實現該方法提供獲取延時任務的倒計時時間

      三、訂單處理

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

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

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

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

      系統內開啟一個線程,不斷的從隊列中獲取消息,獲取到之后對延時消息進行處理。DelayQueue的take方法從隊列中獲取延時任務對象,如果隊列元素數量為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());
              //根據order訂單信息,去查詢該訂單的支付信息
              //如果用戶沒有進行支付,將訂單從數據庫中關閉
              //如果訂單并發量比較大,這里可以考慮異步或線程池的方式進行處理
            }
          }).start();
        }
      }
      

      需要說明的是,這里的while-true循環的延時任務處理時順序執行的,在訂單并發量比較大的時候,需要考慮異步處理的方式完成訂單的關閉操作。我之前寫作一個SpringBoot的可觀測、易配置的線程池開源項目,可能會對你有幫助,源代碼地址:https://gitee.com/hanxt/zimug-monitor-threadpool
      經過我的測試,放入orderDelayQueue的延時任務,在半小時之后得到正確的執行處理。說明我們的實現是正確的。

      四、優缺點

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

      它的缺點就是所有的操作都是基于應用內存的,一旦出現應用單點故障,可能會造成延時任務數據的丟失。如果訂單并發量非常大,因為DelayQueue是無界的,訂單量越大,隊列內的對象就越多,可能造成OOM的風險。所以使用DelayQueue實現延時任務,只適用于任務量較小的情況。
      歡迎關注我的公告號:字母哥雜談,回復003贈送作者專欄《docker修煉之道》的PDF版本,30余篇精品docker文章。字母哥博客:zimug.com

      posted @ 2022-08-18 14:15  字母哥博客  閱讀(1168)  評論(3)    收藏  舉報
      主站蜘蛛池模板: 亚洲日韩国产精品第一页一区 | 天堂在线最新版av观看| 国产成人精品18| 中文字幕人妻有码久视频| 自拍视频在线观看成人| 亚洲人成网网址在线看| 精品一区二区三区少妇蜜臀| 99精品国产成人一区二区| 日韩亚av无码一区二区三区| 亚洲东京色一区二区三区| 色欲久久久天天天综合网| 亚洲欧美偷国产日韩| 国产偷国产偷亚洲高清日韩| 丝袜老师办公室里做好紧好爽| 久久久精品94久久精品| 在线欧美中文字幕农村电影| 伊人色综合一区二区三区影院视频| 不卡国产一区二区三区| 久久99精品久久久久久青青| 樱花草在线社区WWW韩国| 国产精品不卡一二三区| AV最新高清无码专区| 任我爽精品视频在线播放| 亚洲中文久久久精品无码| 91久久精品国产性色也| 亚洲精品国产av成拍色拍个| 国产亚洲一区二区三不卡| 国产国产午夜福利视频| 无码熟妇αⅴ人妻又粗又大| 日本丰满人妻xxxxxhd| 精品国产一区av天美传媒| 日韩一卡二卡三卡四卡五卡| 欧美激情视频一区二区三区免费| 韩国无码AV片午夜福利| 国内熟妇人妻色在线三级| 香蕉久久国产精品免| 国产区成人精品视频| 精品嫩模福利一区二区蜜臀| 欲香欲色天天天综合和网| 国产午夜福利视频第三区| 国产精品白嫩初高生免费视频|