“推迟”任务(或“等待空闲”)真的很难吗?

时间:2013-03-21 20:11:26

标签: java timer scheduled-tasks

如何使用以下属性完成“等待空闲”模型:

  • 当调用方法do()时,在X延迟之后,将调用close()方法。
  • 如果我在 X时间过后再次调用do()方法,则必须延迟对close()的调用。

示例

场景1 :(超时= 10秒):

  1. 用户在do()时调用0
  2. 10时间,调用close()方法,因为用户尚未再次调用do()
  3. 场景2 :(也超时= 10秒):

    1. 用户在时间do()致电0。 (因此,10应调用close()方法。
    2. 8时,用户再次拨打do()
    3. 10时没有任何事情发生,因为close()推迟了10秒。
    4. 18时间,调用close()方法,因为用户自do()后未再次调用8
    5. 我尝试了什么:

      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次。

      我应该怎样做才能让它以高效和整洁的方式运作? (这真的很难吗?)

3 个答案:

答案 0 :(得分:4)

你是正确的,并不是一个艰难的。

这是我想要你的建议。仅创建一次计时器。使它成为课程的一员。在构造函数中创建其实例。

调用方法时,像现在一样创建任务。但是,您可以创建单独的类,甚至可以提前创建实例,并且在调用do()方法时只需安排它,因此将根据您的计划调用close()

调用do()时取消先前创建的关闭任务。如果再次调用方法do(),这将确保您不会关闭任何内容。

顺便说一句,因为do是java中的保留字,所以不能以这种方式调用方法。这意味着您的代码甚至无法编译。更改名称。

答案 1 :(得分:1)

open()

时设置10秒计时器任务

保持变量long lastCallSystem.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");
    }

}