转载。 https://blog.csdn.net/goldenfish1919/article/details/50923450
1.我们以支付以后7天自动收货为例来说明下:
(1)用户支付完成以后,把订单ID插入到内存的一个DelayQueue中,同时插入到Redis中。
(2)7天之内,用户点击了确认收货,则从DelayQueue中删除,从Redis中删除。
(3)超过7天,DelayQueue中的订单ID出队,查询数据库,改状态为自动收货,删除redis。
(4)如果7天之内,web服务器重启过,则web服务器启动以后,从redis中读取待收货的订单,插入到DelayQueue。
看下具体的代码:
@RequestMapping(value = "")
public class OrderController {
DelayService delayService;
RedisService redisServie;
ConfigService configService;
private List<Long> ordeIds = new ArrayList<Long>();
private static final Logger log = Logger.getLogger(OrderController.class);
@RequestMapping(value = "/order", method = RequestMethod.GET)
public String order(final HttpServletRequest request, final Model model) {
@RequestMapping(value = "/pay", method = RequestMethod.GET)
public Response<Void> pay(final HttpServletRequest request, final Model model) {
final long orderId = Long.parseLong(request.getParameter("orderId"));
log.error("订单已支付:"+orderId);
ThreadPoolUtil.execute(new Runnable(){
DSHOrder dshOrder = new DSHOrder(orderId, configService.getDshTimeOut());
delayService.add(dshOrder);
log.error("订单入队:"+orderId);
redisServie.set(Constants.RedisKey.DSH_PREFIX+orderId, dshOrder, RedisService.DB.DSH);
log.error("订单入redis:"+orderId);
return new Response<Void>(0,"成功");
@RequestMapping(value = "/confirm_delivery", method = RequestMethod.GET)
public Response<Void> confirm_delivery(final HttpServletRequest request, final Model model) {
final long orderId = Long.parseLong(request.getParameter("orderId"));
log.error("订单已确认收货:"+orderId);
ThreadPoolUtil.execute(new Runnable(){
delayService.remove(orderId);
log.error("订单手动出队:"+orderId);
redisServie.delete(Constants.RedisKey.DSH_PREFIX+orderId, RedisService.DB.DSH);
log.error("订单手动出redis:"+orderId);
return new Response<Void>(0,"成功");
public class DelayService {
private static final Logger log = Logger.getLogger(DelayService.class);
ConfigService configService;
private OnDelayedListener listener;
private DelayQueue<DSHOrder> delayQueue = new DelayQueue<DSHOrder>();
public static interface OnDelayedListener{
public void onDelayedArrived(DSHOrder order);
public void start(OnDelayedListener listener){
log.error("DelayService 启动");
this.listener = listener;
new Thread(new Runnable(){
DSHOrder order = delayQueue.take();
if(DelayService.this.listener != null){
DelayService.this.listener.onDelayedArrived(order);
public void add(DSHOrder order){
public boolean remove(DSHOrder order){
return delayQueue.remove(order);
public void add(long orderId){
delayQueue.put(new DSHOrder(orderId, configService.getDshTimeOut()));
public void remove(long orderId){
DSHOrder[] array = delayQueue.toArray(new DSHOrder[]{});
if(array == null || array.length <= 0){
for(DSHOrder order : array){
if(order.getOrderId() == orderId){
delayQueue.remove(target);
public class DSHOrder implements Delayed {
public DSHOrder(long orderId, int timeout){
this.startTime = System.currentTimeMillis() + timeout*1000L;
public int compareTo(Delayed other) {
if(other instanceof DSHOrder){
DSHOrder otherRequest = (DSHOrder)other;
long otherStartTime = otherRequest.getStartTime();
return (int)(this.startTime - otherStartTime);
public long getDelay(TimeUnit unit) {
return unit.convert(startTime - System.currentTimeMillis(), TimeUnit.MILLISECONDS);
result = prime * result + (int) (orderId ^ (orderId >>> 32));
result = prime * result + (int) (startTime ^ (startTime >>> 32));
public boolean equals(Object obj) {
if (getClass() != obj.getClass())
DSHOrder other = (DSHOrder) obj;
if (orderId != other.orderId)
if (startTime != other.startTime)
public long getStartTime() {
public long getOrderId() {
public void setOrderId(long orderId) {
public void setStartTime(long startTime) {
this.startTime = startTime;
public String toString() {
return "DSHOrder [orderId=" + orderId + ", startTime=" + startTime + "]";
public class StartupListener implements ApplicationListener<ContextRefreshedEvent> {
private static final Logger log = Logger.getLogger(StartupListener.class);
DelayService delayService;
RedisService redisService;
public void onApplicationEvent(ContextRefreshedEvent evt) {
log.error(">>>>>>>>>>>>系统启动完成,onApplicationEvent()");
if (evt.getApplicationContext().getParent() == null) {
delayService.start(new OnDelayedListener(){
public void onDelayedArrived(final DSHOrder order) {
ThreadPoolUtil.execute(new Runnable(){
long orderId = order.getOrderId();
log.error("自动确认收货,onDelayedArrived():"+orderId);
redisService.delete(Constants.RedisKey.DSH_PREFIX+orderId, RedisService.DB.DSH);
log.error("自动确认收货,删除redis:"+orderId);
ThreadPoolUtil.execute(new Runnable(){
List<String> keys = redisService.scan(RedisService.DB.DSH);
if(keys == null || keys.size() <= 0){
log.error("需要入队的订单keys:"+keys);
DSHOrder order = redisService.get(key, DSHOrder.class, RedisService.DB.DSH);
log.error("读redis,key:"+key);
log.error("订单自动入队:"+order.getOrderId());
最新的代码:https://github.com/xjs1919/util/tree/master/src/main/java/com/github/xjs/util/delay