又看到一种延迟队列的方法 哈哈哈 感觉很好 (订单超时自动关闭)

无意看到一个延时队列的方式 比之前的要好用 哈哈哈 贴出来

首先 定义一个Task 任务类 记录唯一标示、过期时间等信息 其他信息可以自己加
public abstract class Task implements Delayed, Runnable
{
    //唯一标示
    private String id = "";
    //过期时间
    private long expire = 0;

    public Task(String id, long delayInMilliseconds){
        this.id = id;
        this.expire = System.currentTimeMillis() + delayInMilliseconds;
    }

    public String getId() {
        return id;
    }

    @Override
    public long getDelay(TimeUnit unit) {
        long diff = this.expire - System.currentTimeMillis();
        return unit.convert(diff, TimeUnit.MILLISECONDS);
    }

    @Override
    public int compareTo(Delayed o) {
        return Ints.saturatedCast(this.expire - ((Task) o).expire);
    }

    @Override
    public boolean equals(Object o) {
        if (this == o) return true;
        if (o == null) return false;
        if (!(o instanceof Task)) {
            return false;
        }
        Task t = (Task)o;
        return this.id.equals(t.getId());
    }

    @Override
    public int hashCode() {
        return this.id.hashCode();
    }
}
再就是 加入任务队列的服务类 TaskService
@Component
public class TaskService
{
    private TaskService taskService;
    private DelayQueue<Task> delayQueue =  new DelayQueue<Task>();

    @PostConstruct
    private void init()
    {
        taskService = this;

        Executors.newSingleThreadExecutor().execute(() ->
        {
            while (true)
            {
                try
                {
                    Task task = delayQueue.take();
                    task.run();
                } catch (Exception e)
                {
                    e.printStackTrace();
                }
            }
        });
    }

    public void addTask(Task task)
    {
        if(delayQueue.contains(task))return;
        delayQueue.add(task);
    }

    public void removeTask(Task task){
        delayQueue.remove(task);
    }
}
再就是 处理需要过期的任务的 执行类  MaterialUnpaidTask
@Slf4j
public class MaterialUnpaidTask extends Task
{
    private int materialId = -1;

    public MaterialUnpaidTask(Integer materialId, long delayInMilliseconds)
    {
        super("MaterialUnpaidTask-" + materialId, delayInMilliseconds);
        this.materialId = materialId;
    }

    public MaterialUnpaidTask(Integer materialId)
    {
        super("MaterialUnpaidTask-" + materialId, ParamKey.taskConf.MATERIAL_UNPAID * 60 * 1000);
        this.materialId = materialId;
    }

    @Override
    public void run()
    {
        log.info("系统开始处理延时任务---检查素材是否加入回收站,没有在回收站就移除---");
        MaterialMapper materialMapper = ApplicationContextProvider.getBean(MaterialMapper.class);
        //这里是拿到需要删除的素材 然后 删除
        Material material = materialMapper.selectMaterialById(this.materialId);
        if(material!=null&&material.getIsDelete()==1)
        {
            materialMapper.deleteMaterialById(material.getMaterialId());
            log.info("线程:"+Thread.currentThread().getName()+",素材:");
        }
        log.info("系统结束处理延时任务---检查素材是否加入回收站,没有在回收站就移除---");
    }
}


其中 MaterialMapper  是自己的 dao层方法 替换为自己的就可以了 逻辑也是一样 替换成自己的
最后 一个 就是 启动项目就需要进行的启动队列的类 TaskStartupRunner
@Component
public class TaskStartupRunner implements ApplicationRunner
{
    @Autowired
    private TaskService taskService;
    @Autowired
    private MaterialMapper materialMapper;

    @Override
    public void run(ApplicationArguments args)
    {
        //循环回收站 获取状态 addTask();
        //启动的时候找到回收站的素材 不区分店铺
        List<Material> materialList = materialMapper.selectGarbage(null);
        for(Material material : materialList)
        {
            LocalDateTime add = LocalDateTimeUtil.ofUTC(material.getDeleteTime());
            LocalDateTime now = LocalDateTime.now();
            LocalDateTime expire =  add.plusSeconds(90);
            if(expire.isBefore(now))
            {
                // 已经过期,则加入延迟队列
                taskService.addTask(new MaterialUnpaidTask(material.getMaterialId(), 0));
            }
            else{
                // 还没过期,则加入延迟队列
                long delay = ChronoUnit.MILLIS.between(now, expire);
                taskService.addTask(new MaterialUnpaidTask(material.getMaterialId(), delay));
            }
        }
    }
}

一样的 相关代码 替换成 自己的就可以了  

到这里基本就OK了  之前也有过一个 那个 启动有些问题 但是我用了这个 问题就没有了 很神奇 虽然 我也不是 超级理解 这个延时队列 但 用起来真的香  哈哈  好了 不懂就问我哦 vx  AiMyHear
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值