一个基本得延迟订单功能做好了,在Test.java里面有测试用例,可以自己扩展更为高效得延迟订单,比如说加入消息队列什么的。下面是链接:
https://pan.baidu.com/s/1HLMeW-EIEqlKA9SDn9ffDw 密码:6t84
下面我们看好着DelayQueue大概是怎样得
put订单得时候,我们会调用offer()方法,offer()方法如下:
public boolean offer(E e) {
final ReentrantLock lock = this.lock;
lock.lock();
try {
//q PriorityQueue优先级队列,实际上是一个堆(不指定Comparator时默认为最小堆)TOP K问题就可以使用它
q.offer(e); //入队
if (q.peek() == e) {
leader = null; //q.peek() == e 时将leader线程置为空
//调用Condition的signal()方法将会唤醒再等待队列中的首节点,该节点也是到目前为止等待时间最长的节点
available.signal();
}
return true;
} finally {
lock.unlock();
}
}
取订单时,使用take(),并且得开线程执行,take方法如下:
public E take() throws InterruptedException {
//lock锁
final ReentrantLock lock = this.lock;
//这个会先判断当前线程是否被中断,然后抛出异常。而使用lock.lock()时,调用interrupt(),也不会抛出异常,一直去获取锁cas
lock.lockInterruptibly();
try {
for (;;) { //这个就不用多说了
E first = q.peek();
if (first == null)
available.await(); //为空等待
else {
long delay = first.getDelay(NANOSECONDS);
if (delay <= 0)
return q.poll(); //过期了出队 ,先进先出
first = null; // don't retain ref while waiting
if (leader != null)
//等待队列中还剩余未过期订单,
available.await();
else {
//take 的线程 这个因为我们take的时候,是在一个线程里while(true){take()}
//因为是只开了一个线程来无限take(),如果存在多个线程一起来take()的时候,leader就有可能失去领导地位
Thread thisThread = Thread.currentThread();
leader = thisThread;
try {
//轮询检查线程是否在同步线程上,如果在则退出自旋。否则检查是否已超过解除挂起时间,如果超过,则退出挂起,否则继续挂起线程到等待解除挂起
available.awaitNanos(delay);
} finally {
if (leader == thisThread)
leader = null;
}
}
}
}
} finally {
if (leader == null && q.peek() != null)
available.signal();
lock.unlock();
}
}
到此结束吧,有兴趣的伙伴,可以想哈为什么使用leader???有什么作用???

本文深入解析了一个基于Java的延迟订单功能实现,通过DelayQueue和ReentrantLock等工具,实现了订单的延迟处理。文章详细介绍了offer()和take()方法的工作原理,并探讨了leader机制的作用。
226

被折叠的 条评论
为什么被折叠?



