使用DelayQueue

使用DelayQueue延迟任务

业务场景:

  • 定单到期自动失效,并向用发送短信或者微信消息模板
  • 缓存失效

解决这类业务也有其他方案:

  • spring + quartz: 每隔几秒钟就去扫描数据库中失效的记录
  • spring + redis (keyspace notification)

缺点:

  • 在单机上是一种不错的选择,但在分布式环境下需要自己实现同步,不如quartz
  • 数据放在内存,需要实现数据持久化,不如quartz

优点:

  • 相比较quartz,就不用每隔几秒钟就去扫描数据库中失效的记录

要使用DelayQueue,要求放入DelayQueue中的实体类实现Delayed接口

public interface Delayed extends Comparable<Delayed> {

    /**
     * Returns the remaining delay associated with this object, in the
     * given time unit.
     *
     * @param unit the time unit
     * @return the remaining delay; zero or negative values indicate
     * that the delay has already elapsed
     */
    long getDelay(TimeUnit unit);
}

DelayTask.java:

public class DelayTask implements Delayed {

    private long expiredTime;
    private String name;

    public DelayTask(long expiredTime, String name) {
        this.expiredTime = expiredTime;
        this.name = name;
    }

    @Override
    public long getDelay(TimeUnit unit) {  //还有多久过期
         //expiredTime时间单位要和当前时间单位统一!!
         return this.expiredTime - System.currentTimeMillis();
    }

    @Override
    public int compareTo(Delayed o) {
        int dif =  (int) (this.getDelay(TimeUnit.NANOSECONDS) -o.getDelay(TimeUnit.NANOSECONDS));
        return dif > 0 ? 1: dif < 0 ? -1:0;
    }

    @Override
    public String toString() {
        return "DelayTask{" +
                "expiredTime=" + expiredTime +
                ", name='" + name + '\'' +
                '}';
    }

}

测试用例:

public static void main(String[] args) throws InterruptedException {
   DelayQueue<DelayTask> queue = new DelayQueue<>();
   SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss:SSS");

   System.out.println("start: "+ sdf.format(new Date()));
   long start = System.currentTimeMillis();
   TimeUnit timeUnit =  TimeUnit.MILLISECONDS;

   queue.add(new DelayTask(timeUnit.convert(10, TimeUnit.SECONDS)+start, "task-1"));
   queue.add(new DelayTask(timeUnit.convert(4, TimeUnit.SECONDS)+ start, "task-2"));
   queue.add(new DelayTask(timeUnit.convert(7, TimeUnit.SECONDS)+start, "task-3"));

   while (!queue.isEmpty()){
       DelayTask task = queue.take();
       if (task != null){
           System.out.println("get task: "+ task+ " at "+ sdf.format(new Date()));
       }
   }
   System.out.println("end...");

}

结果:

start: 2018-04-06 10:50:45:538
get task: DelayTask{expiredTime=1522983049543, name='task-2'} at 2018-04-06 10:50:49:543  -->与开始时间相差4秒
get task: DelayTask{expiredTime=1522983052543, name='task-3'} at 2018-04-06 10:50:52:543  -->与开始时间相差7秒
get task: DelayTask{expiredTime=1522983055543, name='task-1'} at 2018-04-06 10:50:55:543  -->与开始时间相差10秒
end...

顺便了解一下TimeUnit:

TimeUnit timeUnit = TimeUnit.HOURS;
System.out.println(timeUnit.convert(2, TimeUnit.DAYS));  将2天转成以小时为单位

//结果
48
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值