使用DelayQueue来实现延时订单
思路:要使用DelayQueue时,必须要先实现Delayed接口,将数据存入其中,并设置过期时间
当DelayQueue中存有元素时,不一定能立即拿到,必须要先等到过期时间过后,这个时候才可以取到元素,根据这个原理可以来实现延时订单的功能
首先,我们先通过新建一个类并实现该接口
public class ItemVo<T> implements Delayed{
private long activeTime;//到期时间,单位毫秒
private T date;
//activeTime是个过期时长
public ItemVo(long activeTime, T date) {
super();
this.activeTime = TimeUnit.NANOSECONDS.convert(activeTime,
TimeUnit.MILLISECONDS)+System.nanoTime();//将传入的时长转换为超时的时刻
this.date = date;
}
public long getActiveTime() {
return activeTime;
}
public T getDate() {
return date;
}
//按照剩余时间排序
@Override
public int compareTo(Delayed o) {
long d = getDelay(TimeUnit.NANOSECONDS)-o.getDelay(TimeUnit.NANOSECONDS);
return (d==0)?0:((d>0)?1:-1);
}
//返回元素的剩余时间
@Override
public long getDelay(TimeUnit unit) {
long d = unit.convert(this.activeTime-System.nanoTime(),
TimeUnit.NANOSECONDS);
return d;
}
}
这个时候,我们可以新建一个订单类,存储在ItemVo的属性中
public class Order {
private final String orderNo;//订单的编号
private final double orderMoney;//订单的金额
public Order(String orderNo, double orderMoney) {
super();
this.orderNo = orderNo;
this.orderMoney = orderMoney;
}
public String getOrderNo() {
return orderNo;
}
public double getOrderMoney() {
return orderMoney;
}
}
我们的订单类创建完毕了,我们可以使用生产者消费者思想,新建两个类,一个类负责添加订单,一个类负责获取订单(当拿到订单的时候,这个时候说明订单已经过期了)
public class PutOrder implements Runnable {
private DelayQueue<ItemVo<Order>> queue;
public PutOrder(DelayQueue<ItemVo<Order>> queue) {
super();
this.queue = queue;
}
@Override
public void run() {
//5秒到期
Order ordeTb = new Order("Tb12345",366);
ItemVo<Order> itemTb = new ItemVo<Order>(5000,ordeTb);
System.out.println(Thread.currentThread().getName()+" 开始加入Tb12345");
queue.offer(itemTb);
System.out.println(queue.size());
System.out.println("订单5秒后到期:"+ordeTb.getOrderNo());
//8秒到期
Order ordeJd = new Order("Jd54321",366);
ItemVo<Order> itemJd = new ItemVo<Order>(8000,ordeJd);
System.out.println(Thread.currentThread().getName()+" 开始加入JD54321");
queue.offer(itemJd);
System.out.println(queue.size());
System.out.println("订单8秒后到期:"+ordeJd.getOrderNo());
}
}
public class FetchOrder implements Runnable {
private DelayQueue<ItemVo<Order>> queue;
public FetchOrder(DelayQueue<ItemVo<Order>> queue) {
super();
this.queue = queue;
}
@Override
public void run() {
while(true) {
try {
ItemVo<Order> item = queue.take();
Order order = (Order)item.getDate();
System.out.println(Thread.currentThread().getName()+" get from queue:"+order.getOrderNo());
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
}
最后,我们新建一个测试类进行测试
public class Test {
public static void main(String[] args) throws InterruptedException {
DelayQueue<ItemVo<Order>> queue = new DelayQueue<>();
new Thread(new PutOrder(queue)).start();
new Thread(new FetchOrder(queue)).start();
//每隔500毫秒,打印个数字
for(int i=1;i<15;i++){
Thread.sleep(500);
System.out.println(i*500);
}
}
}
好了,我们的延时订单测试成功