如何使用以下属性完成“等待空闲”模型:
do()
时,在X延迟之后,将调用close()
方法。do()
方法,则必须延迟对close()
的调用。示例
场景1 :(超时= 10秒):
do()
时调用0
。10
时间,调用close()
方法,因为用户尚未再次调用do()
。场景2 :(也超时= 10秒):
do()
致电0
。 (因此,10
应调用close()
方法。8
时,用户再次拨打do()
。10
时没有任何事情发生,因为close()
推迟了10秒。18
时间,调用close()
方法,因为用户自do()
后未再次调用8
。我尝试了什么:
private static final long delay = 10000;
private Timer t;
private TimerTask tt;
public void do() {
...
// check old timer first:
if (t != null) t.cancel();
// create new timer
t = new Timer();
tt = new TimerTask() {
@Override
public void run() {
close();
}
}
// run it
t.schedule(tt, System.currentTimeMillis() + delay);
}
private void close() {
// do some cleanup here
}
这段代码非常难看。
它也非常低效且占用大量内存,因为do()
函数每秒调用约50次。
我应该怎样做才能让它以高效和整洁的方式运作? (这真的很难吗?)
答案 0 :(得分:4)
你是正确的,并不是一个艰难的。
这是我想要你的建议。仅创建一次计时器。使它成为课程的一员。在构造函数中创建其实例。
调用方法时,像现在一样创建任务。但是,您可以创建单独的类,甚至可以提前创建实例,并且在调用do()
方法时只需安排它,因此将根据您的计划调用close()
。
调用do()
时取消先前创建的关闭任务。如果再次调用方法do()
,这将确保您不会关闭任何内容。
顺便说一句,因为do
是java中的保留字,所以不能以这种方式调用方法。这意味着您的代码甚至无法编译。更改名称。
答案 1 :(得分:1)
在open()
保持变量long lastCall
从System.currentTimeMillis()
doIt()
在时间任务正文中,检查lastCall
是否在10秒内。如果是,请重新安排计时器任务剩余时间。如果没有,请致电close()
当您从synchronize
读取或写信时,不要忘记lastCall
某事
答案 2 :(得分:0)
我找到了合适的解决方案:
public class TimerExample {
private TimerTask tt;
ScheduledFuture<?> future;
private ScheduledThreadPoolExecutor s;
public TimerExample() {
s = new ScheduledThreadPoolExecutor(1);
tt = new TimerTask() {
@Override
public void run() {
close();
}
};
doSomething();
}
public void doSomething() {
if (future != null) future.cancel(true);
future = s.schedule(tt, 3000, TimeUnit.MILLISECONDS);
System.out.println("do");
}
public void close() {
System.out.println("Close");
}
}