美文网首页
定时任务是恶魔(一)

定时任务是恶魔(一)

作者: 黄云斌huangyunbin | 来源:发表于2018-10-29 10:25 被阅读0次

cache是个好东西,guava的lodingcache是好东西。

问题1:如何自定义过期逻辑

但是lodingcache只能基于访问时间的过期,假如有其他过期逻辑的时候,还是要自己写。

这就开始了我的坑爹之旅。

我有个LocalLock类,是对java的ReentrantLock的封装,ReentrantLock在使用的时候自然是不能过期回收的。

有对应的api:reentrantLock.isLocked()

    public boolean canUse() {
        long noUseTime = System.currentTimeMillis() - lastUseTime;
        if (noUseTime > canUseTime && !reentrantLock.isLocked()) {
            return false;
        }
        return true;
    }

然后我就很高兴的写个定时任务来清除过期的了。

        this.schedule.scheduleWithFixedDelay(new Runnable() {
            @Override
            public void run() {
                checkNoUse();
            }
        }, 10, 10, TimeUnit.SECONDS);
    private void checkNoUse() {
        Iterator<Map.Entry<String, LocalLock>> iterator = cache.entrySet().iterator();
        while (iterator.hasNext()) {
            LocalLock lock = iterator.next().getValue();
            if (!lock.canUse()) {
                iterator.remove();
            }
        }
    }

问题2:这个是有并发问题的
  • 时序1 定时任务线程可以回收的
  • 时序2 业务线程加锁变成不可回收了
  • 时序3 定时任务线程remove删除

    这样就把不该回收的对象删除了。
解决办法

synchronized

    public synchronized boolean canUse() {

这个synchronized对应两个场景,一个是定时任务,一个就是从缓存中拿对象

private LocalLock getLock(String key) {
        LocalLock lock = cache.get(key);
        if (lock != null && lock.canUse()) {
            return lock;
        }

问题3:发现还是有并发问题

从缓存中拿到对象还是可用的,正要开始使用,定时任务判断过期了,回收掉。。

解决办法:

缓存中拿对象的同时,修改最后使用时间,保证一段时间内不会被定时任务回收。

愉快的修改代码为:

public synchronized boolean canUseAndRefresh() {
        long noUseTime = System.currentTimeMillis() - lastUseTime;
        if (noUseTime > canUseTime && !reentrantLock.isLocked()) {
            return false;
        }
        lastUseTime = System.currentTimeMillis();       
        return true;
    }

问题4:发现定时任务永远回收不了

因为定时任务每次都修改了最后访问时间,相当于定时任务在续命了,永远不会过期。

解决办法:

canUseAndRefresh加个参数区分两个逻辑,定时任务就不修改最后访问时间了。

public synchronized boolean canUseAndRefresh(boolean refresh) {
        long noUseTime = System.currentTimeMillis() - lastUseTime;
        if (noUseTime > canUseTime && !reentrantLock.isLocked()) {
            return false;
        }
        if (refresh) {
            lastUseTime = System.currentTimeMillis();
        }
        return true;
    }

整个方案还是比较复杂的,而且可以看到有很多坑,那还有其他的解决办法吗?

相关文章

  • 定时任务是恶魔(一)

    cache是个好东西,guava的lodingcache是好东西。 问题1:如何自定义过期逻辑 但是lodingc...

  • 定时任务是恶魔(二)

    上文的需求其实非常适合用guava的loadingCache来实现的,问题就是如何自定义过期逻辑呢 找了很久,发现...

  • 分布式定时调度-xxl-job

    一、定时任务概述 1.1 定时任务认识 1.1.1 什么是定时任务 定时任务是按照指定时间周期运行任务。使用场景为...

  • 2019-07-31定时任务

    定时任务 定时任务实现方法 系统默认定时任务 用户自定义设置定时任务 定时任务配置文件 定时任务启动 定时任务样例...

  • 7月30日 定时任务

    定时任务 代替人自动完成一些任务 定时任务实现的方法 定时任务软件:cronie定时任务软件:atd --- 设...

  • day 17

    第13章 Linux系统定时任务Cron(d)服务应用实践 1.1、Linux定时任务 1.1.1、什么是定时任务...

  • 23笔记---定时任务

    今日内容 定时任务1.什么是定时任务2.为什么用定时任务3.定时任务使用情况4.定时任务如何使用5.书写时的规范 ...

  • day 22 操作系统定时任务

    系统定时任务概念==生活中闹钟 系统定时任务实现方法: 实现定时任务配置: 定时任务如何进行设置 定时任务编写常见...

  • 自动化 - 定时任务

    定时任务是系统定期执行的任务 1.定时任务解说 在MisShop平台中,定时任务的本质就是一个立即执行页面,到点了...

  • crontab 定时任务

    查看当前用户的定时任务列表 创建(编辑)定时任务列表 定时任务格式 删除定时任务 注意 一定要设置crontab的...

网友评论

      本文标题:定时任务是恶魔(一)

      本文链接:https://www.haomeiwen.com/subject/qrivtqtx.html