DelayQueue是什么?
DelayQueue是一个无界的BlockingQueue(阻塞队列),用于放置实现了Delayed接口的对象,其中的对象只能在其到期时才能从队列中取走。这种队列是有序的,即队头对象的延迟到期时间最长。
注意:不能将null元素放置到这种队列中。
DelayQueue能做什么?
1. 淘宝订单业务:下单之后如果三十分钟之内没有付款就自动取消订单。
2. 饿了吗订餐通知:下单成功后60s之后给用户发送短信通知。
3.关闭空闲连接。服务器中,有很多客户端的连接,空闲一段时间之后需要关闭之。
4.缓存。缓存中的对象,超过了空闲时间,需要从缓存中移出。
5.任务超时处理。在网络协议滑动窗口请求应答式交互时,处理超时未响应的请求等。
注意
DelayQueue 没有持久化,重启服务器后消息会丢失。看业务需求使用。
代码片段
import java.util.Iterator;
import java.util.Map;
import java.util.concurrent.DelayQueue;
import java.util.concurrent.Executors;
import javax.annotation.PostConstruct;
import org.springframework.context.annotation.Lazy;
import org.springframework.stereotype.Component;
import com.alibaba.fastjson.JSON;
import com.cxtrip.utils.LogUtils;
import com.cxtrip.utils.NullUtils;
import com.cxtrip.utils.ServiceNoticeUtil;
@Component
@Lazy(false)
public class DelayOrderComponent{
private static DelayQueue<OrderMessage> delayQueue = new DelayQueue<OrderMessage>();
@PostConstruct
public void init() throws Exception {
/**启动单线程池,去取延迟消息**/
Executors.newSingleThreadExecutor().execute(new Runnable() {
@Override
public void run() {
OrderMessage message = null;
// 不断的获取队列消息(只有到期的数据才会被取出来)
while (true) {
try {
// 取出队列消息
message = delayQueue.take();
// 业务逻辑-------------
} catch (Exception e) {
e.printStackTrace();
}
}
}
});
}
/**加入延迟消息队列**/
public static boolean addOrderDelayQueue(OrderMessage orderMessage){
return delayQueue.add(orderMessage);
}
}
Delayed对象
import java.util.Date;
import java.util.concurrent.Delayed;
import java.util.concurrent.TimeUnit;
import com.cxtrip.utils.DateUtils;
public class OrderMessage implements Delayed {
private final String orderId;//序号
private final long startTime ;//开始时间
private final long expire ;//到期时间
private final Date now; //创建时间
private final String orderMsg;//其他信息JSON方式保存,备用字段,可存储对象字段(对象转JSON)
// secondsDelay 延迟多少秒
public OrderMessage(String orderId, String startTimeStr, String orderMsg ,long secondsDelay) {
super();
this.orderId = orderId;
this.startTime = DateUtils.date2Time(startTimeStr, "yyyyMMddHHmmss");
this.expire = startTime + (secondsDelay*1000);
this.orderMsg = orderMsg;
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);
}
public String getOrderId() {
return orderId;
}
public String getOrderMsg() {
return orderMsg;
}
public Date getNow() {
return now;
}
public long getStartTime() {
return startTime;
}
public long getExpire() {
return expire;
}
}