java延時隊列使用

在實際的業務中會遇到如下場景:
1)過1分鐘失敗任務重試
2)過1小時發送郵件
等等,需要延時一段時間處理,在java的juc包中給我提供了DelayQueue延時隊列處理,過一會該處理的事兒。
DelayQueue<E extends Delayed>,一個無界阻塞隊列,只有在延遲期滿時才能從中提取元素。該隊列的頭部是延遲期滿後保存時間最長的Delayed元素。如果延遲都還沒有期滿,則隊列沒有頭部,並且 poll 將返回 null。當一個元素的 getDelay(TimeUnit.NANOSECONDS) 方法返回一個小於等於 0 的值時,將發生到期。即使無法使用 take 或 poll 移除未到期的元素,也不會將這些元素作爲正常元素對待。例如,size 方法同時返回到期和未到期元素的計數。此隊列不允許使用 null 元素。

下面通過代碼演示這一場景:

1.新建消息實現Delayed接口

package cn.slimsmart.study.queue;

import java.util.concurrent.Delayed;
import java.util.concurrent.TimeUnit;

/**
 * 延時消息實體
 * @author slimina
 *
 */
public class Message implements Delayed{
	
	private int id;  
    private String body;  //消息內容
    private long excuteTime;//執行時間    
    
    public int getId() {
		return id;
	}

	public void setId(int id) {
		this.id = id;
	}

	public String getBody() {
		return body;
	}

	public void setBody(String body) {
		this.body = body;
	}

	public long getExcuteTime() {
		return excuteTime;
	}

	public void setExcuteTime(long excuteTime) {
		this.excuteTime = excuteTime;
	}

	public Message(int id, String body,long delayTime) {  
        this.id = id;  
        this.body = body;  
        this.excuteTime = TimeUnit.NANOSECONDS.convert(delayTime, TimeUnit.MILLISECONDS) + System.nanoTime();  
    } 

	@Override
	public int compareTo(Delayed delayed) {
		Message msg = (Message)delayed;  
        return Integer.valueOf(this.id)>Integer.valueOf(msg.id)?1:( Integer.valueOf(this.id)<Integer.valueOf(msg.id)?-1:0);  
	}

	@Override
	public long getDelay(TimeUnit unit) {
		return  unit.convert(this.excuteTime - System.nanoTime(), TimeUnit.NANOSECONDS);   
	}

}
2.創建消費者

package cn.slimsmart.study.queue;

import java.util.concurrent.DelayQueue;

//消費者
public class Consumer implements Runnable {

	// 延時隊列
	private DelayQueue<Message> queue;

	public Consumer(DelayQueue<Message> queue) {
		this.queue = queue;
	}

	@Override
	public void run() {
		while (true) {
			try {
				Message take = queue.take();
				System.out.println("消費消息:" + take.getId() + ":" + take.getBody());
			} catch (InterruptedException e) {
				e.printStackTrace();
			}
		}
	}
}
3.向延時隊列發送消息

package cn.slimsmart.study.queue;

import java.util.concurrent.DelayQueue;

public class DelayQueueTest {

	public static void main(String[] args) {
		// 創建延時隊列
		DelayQueue<Message> queue = new DelayQueue<Message>();
		// 添加延時消息,m1 延時5s
		Message m1 = new Message(1, "world", 3000);
		// 添加延時消息,m2 延時3s
		Message m2 = new Message(2, "hello", 10000);
		queue.offer(m2);
		queue.offer(m1);
		// 啓動消費線程
		new Thread(new Consumer(queue)).start();
	}

}
運行可以看到消息接收的時間間隔。
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章