延迟队列实现之Netty

首先我们了解是时间轮的算法:

在这里插入图片描述
时间轮:就像上面的时间盘,里面有8个格子组成一个时间轮,如果每个格子代表的时间为1s,那么一圈的就代表8秒。
加入我们将延迟任务加入时间轮的时间为时间轮中0秒的位置,延迟5秒执行,那就是说当转到6个格子的时候就会开始执行定时任务,如果超过8秒,需要延时20秒的,那就需要转多个圈。按以上实例,需要转2圈+4个格子,那就那就是转了2圈后在5标号的格子开始。
首先我们看下netty 中的时间轮类
Netty构建延时队列主要用HashedWheelTimer,HashedWheelTimer底层数据结构依然是使用DelayedQueue,只是采用时间轮的算法来实现。
首先来看一下构造方法
在这里插入图片描述
该类提供了多种构造方法。
主要构造方法参数
ThreadFactory threadFactory 表示用于生成工作线程,一般采用线程池;
long tickDuration 每格的时间间隔,默认100ms;
TimeUnit unit 时间单位
int ticksPerWheel 一圈的总格子数,默认512
下面我们看下他的默认无参构造方法
在这里插入图片描述
在这里插入图片描述
实现代码
1、定义订单实体类

@Data
public class Order {

    /**
     * 订单编号
     */
    private String orderNo;
    /**
     * 价格(元)
     */
    private BigDecimal price;
    /**
     * 商品数量
     */
    private int prodductNum;
    /**
     * 总金额
     */
    private BigDecimal totalAmount;

    /**
     * 创建时间
     */
    private Date createTime;


}

定义任务实体类

public class DelayTask implements TimerTask {

    private Order order;
    private boolean expiredFlag;

    public DelayTask(Order order, boolean expiredFlag) {
        this.order = order;
        this.expiredFlag = expiredFlag;
    }

    @Override
    public void run(Timeout timeout) throws Exception {
        //此处编写执行订单超时状态的逻辑代码
        final String nowformat = DateUtil.format(new Date(), "yyyy-MM-dd HH:mm:ss");
        final long diff = (new Date().getTime() - order.getCreateTime().getTime()) / 1000;
        System.out.println(order.getOrderNo() + "订单已经超时了" + "失效时间" +diff+"秒" );
    }
}

定时时间轮,执行任务

public class OrderDelayTask {

    /**
     * 定义时间轮对象,每个延迟任务一个
     */
    private static final  Timer wheelTimer = new HashedWheelTimer();

    /**
     * @param order       订单信息
     * @param expiredTime 超时时间
     * @param unit        超时单位
     */
    public static void executeDelayTask(Order order, int expiredTime, TimeUnit unit) {
        //创建订单任务
        final DelayTask delayTask = new DelayTask(order, true);
        //执行延迟队列
        wheelTimer.newTimeout(delayTask, expiredTime, unit);
    }
}

定义测试方法

 public static void main(String[] args) throws InterruptedException {
        Order order = null;
        for (int i = 0; i < 10; i++) {
            // Thread.sleep(1000);
            order = new Order();
            order.setOrderNo(new Snowflake().nextIdStr());
            order.setCreateTime(new Date());
            OrderDelayTask.executeDelayTask(order, 10, TimeUnit.SECONDS);
        }
    }

实现结果截图
在这里插入图片描述
有点:代码实现简单
缺点:对内存消耗较大,集群部署不友好。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值