自我到期的对象 - 任何更好的选择

时间:2013-08-06 09:11:10

标签: java

请在下面找到我创建并打算用作自定义对象的类。

public class SelfExpiringObject {

    private boolean expired;
    // other properties

    public void setValidity(final int seconds) {
        new Timer().schedule(new TimerTask() {
            public void run() {
                expired = true;
            }
        }, TimeUnit.SECONDS.toMillis(seconds));
    }

    public boolean isExpired() {
        return expired;
    }
}

任何人都可以提出更好的选择吗?

想在规则引擎中使用它来处理事件。其中一个场景是收到事件时,将它们放入会话中(使用具有自失效属性的对象)。我希望他们仅按照规则中设置的有效性进入会话。一旦它们到期,它们将被从会话中删除。

5 个答案:

答案 0 :(得分:7)

懒洋洋地计算到期时间:

private long expiryDate; // set in constructor

public boolean isExpired() {
    return System.currentTimeMillis() >= expiryDate;
}

无需生成线程。

答案 1 :(得分:5)

每个Timer创建一个线程,这是一个非常昂贵的对象。我建议您只在对象中有到期时间,并有一个线程定期删除过期的对象。

public class ExpiringObject {

    private long expiresMS;
    // other properties

    public void setValidity(final int seconds) {
        expiresMS = System.currentTimeMillis() + seconds * 1000;
    }

    public boolean isExpired() {
        return System.currentTimeMillis() >= expireMS;
    }
}

监视这些项目的线程可以在Drools过期时更新。

答案 2 :(得分:3)

您可以简单地使用时间戳来代替计时器:

public class SelfExpiringObject {
    private long timestamp;

    private boolean expired;
    // other properties

    public void setValidity(final int seconds) {
        timestamp = System.currentTimeMillis() + 1000 * seconds;
    }

    public boolean isExpired() {
        if (!expired) {
            expired = System.currentTimeMillis() >= timestamp;
        } 
        return expired;
    }
}

答案 3 :(得分:3)

答案 4 :(得分:2)

  • 如果你有很多事件,那么每个事件创建一个Timer效率不会很高。
  • ScheduledExecutor往往更健壮。
  • 您的代码不是线程安全的,并且在Timer运行后调用isExpired的代码可能仍会看到false - 最简单的方法是标记变量volatile

所以你的类看起来像这样(虽然我更喜欢其他提议的方法来完全删除线程并改为使用时间戳):

public class SelfExpiringObject {

    private final ScheduledExecutorService scheduler;
    private volatile boolean expired = false;
    // other properties

    public SelfExpiringObject(ScheduledExecutorService scheduler) {
        this.scheduler = scheduler;
    }

    public void setValidity(final int seconds) {
        scheduler.schedule(new Runnable() {
            public void run() {
                expired = true;
            }
        }, seconds, TimeUnit.SECONDS);
    }

    public boolean isExpired() {
        return expired;
    }
}

创建ScheduledExecutorService:

ScheduledExecutorService scheduler = Executors.newScheduledThreadPool(poolSize);