java併發編程工具類JUC第三篇:DelayQueue延時隊列

DelayQueue 是BlockingQueue接口的實現類,它根據"延時時間"來確定隊列內的元素的處理優先級(即根據隊列元素的“延時時間”進行排序)。另一層含義是隻有那些超過“延時時間”的元素才能從隊列裏面被拿出來進行處理。

  • DelayQueue 隊列將阻止其元素對象從隊列中被取出,直到達到爲元素對象設置的延遲時間。DelayQueue 在隊列的頭部存儲最近過期的元素,如果隊列內沒有元素過期,使用poll()方法獲取隊列內的元素將會返回null。
  • DelayQueue 類及其迭代器實現了CollectionIterator接口的所有可選方法,但迭代器方法iterator()不能保證以特定的順序遍歷DelayQueue的元素。

  • DelayQueue 不接收null元素,DelayQueue 只接受那些實現了java.util.concurrent.Delayed接口的對象,並將其放入隊列內。DelayQueue 通過調用元素對象的getDelay(TimeUnit) 方法獲取該元素剩餘的“延遲時間”。getDelay()的 TimeUnit時間單位是一個枚舉類型 : DAYS(天), HOURS(小時), MINUTES(分鐘), SECONDS(秒), MILLISECONDS(毫秒), MICROSECONDS(微妙), NANOSECONDS(納秒)
public interface Delayed extends Comparable{
   long getDelay(TimeUnit unit);
}

下面我們就寫一個java Class實現Delayed 接口,只有實現了Delayed 接口的類對象才能放入DelayQueue。因爲Delayed接口繼承自Comparable接口,所以我們必須實現getDelay方法和compareTo方法。

class DelayObject implements Delayed {
    private String name; 
    private long time;   //延時時間

    public DelayObject(String name, long delayTime) { 
      this.name = name; 
      this.time = System.currentTimeMillis() + delayTime; 
    } 

   [@Override](https://my.oschina.net/u/1162528)
   public long getDelay(TimeUnit unit) {
      long diff = time - System.currentTimeMillis(); 
      return unit.convert(diff, TimeUnit.MILLISECONDS); 
   } 

   [@Override](https://my.oschina.net/u/1162528)
   public int compareTo(Delayed obj) { 
      if (this.time < ((DelayObject)obj).time) { 
         return -1; 
      } 
      if (this.time > ((DelayObject)obj).time) { 
         return 1; 
      } 
      return 0; 
   } 

   [@Override](https://my.oschina.net/u/1162528)
   public String toString() {
     Date date = new Date(time);
     SimpleDateFormat sd = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");

     return "\nDelayObject:{"
       + "name=" + name
       + ", time=" +  sd.format(date)
       + "}";
   } 
} 

測試延時隊列DelayQueue的使用效果

public class DelayQueueTest {

  [@Test](https://my.oschina.net/azibug)
  void testDelayObject() throws InterruptedException {

    //實例化一個DelayQueue
    BlockingQueue<DelayObject> DQ = new DelayQueue<>();

    //向DelayQueue添加四個元素對象,注意延時時間不同
    DQ.add(new DelayObject("A", 1000 * 10));  //延時10秒
    DQ.add(new DelayObject("B", 4000 * 10));  //延時40秒
    DQ.add(new DelayObject("C", 3000 * 10));  //延時30秒
    DQ.add(new DelayObject("D", 2000 * 10));  //延時20秒

    SimpleDateFormat sd = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");

    //將對象從DelayQueue取出,注意取出的順序與延時時間有關
    System.out.println( DQ.take());  //取出A
    System.out.println( DQ.take());  //取出D
    System.out.println( DQ.take());  //取出C
    System.out.println( DQ.take());  //取出B

  }
}

從下面的打印結果及上文的代碼可以看出

  • 隊列中元素放入的順序是A、B、C、D,取出的順序是A、D、C、B,這是因爲隊列中的元素按照延時時間進行了排序。
  • 另外我們可以看到,每隔10秒纔可以從隊列中取出一個元素,這是因爲只有超過“延時時間”的元素才能從隊列裏面被拿出來。而我們設置的延時時間是10s、20s、30s、40s。
DelayObject:{name=A, time=2021-03-23 14:14:20}

DelayObject:{name=D, time=2021-03-23 14:14:30}

DelayObject:{name=C, time=2021-03-23 14:14:40}

DelayObject:{name=B, time=2021-03-23 14:14:50}

歡迎關注我的博客,裏面有很多精品合集

本文轉載註明出處(必須帶連接,不能只轉文字):字母哥博客 - zimug.com

覺得對您有幫助的話,幫我點贊、分享!您的支持是我不竭的創作動力! 。另外,筆者最近一段時間輸出瞭如下的精品內容,期待您的關注。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章