代码之家  ›  专栏  ›  技术社区  ›  Roshana Pitigala Laxmansinghsodhanohdiyala

延迟java.util.Timer 再过x秒

  •  1
  • Roshana Pitigala Laxmansinghsodhanohdiyala  · 技术社区  · 6 年前

    我在试着运行一个 java.util.Timer Thread.sleep() ,我写了下面的代码。

    Timer t = new Timer();
    
    t.schedule(new TimerTask() {
        @Override
        public void run() {
            if (true) { //When this is false timer should continue at 3 second interval.
                try {
                    Thread.currentThread().sleep(2000); //Delay by another 2 seconds.
                } catch (Exception ex) {
                    ex.printStackTrace();
                }
            }
            System.out.println(new Date());
        }
    }, 0, 3000); //Trigger every 3 seconds.
    

    我要打印时间戳,相差5秒。但我得到的是3秒的差异。

    Tue Sep 18 15:08:17 IST 2018
    Tue Sep 18 15:08:20 IST 2018
    Tue Sep 18 15:08:23 IST 2018
    Tue Sep 18 15:08:26 IST 2018
    Tue Sep 18 15:08:29 IST 2018
    

    我错过了什么?

    2 回复  |  直到 6 年前
        1
  •  2
  •   jbx    6 年前

    你2秒钟的睡眠只是在3秒钟的时间间隔内模拟2秒钟的工作 TimerTask 触发器。所以在你睡觉后大约1秒,你的计时器会再次启动。

    但是,请记住,以这种方式延迟不是很稳定。计时器将考虑所有落后于计划的任务,并在前一个任务完成时按顺序触发它们。如果你真的想这样做的话,最好是取消任务,把它们重新安排到5秒的时间间隔。

        2
  •  1
  •   mdewit    6 年前

    您当前的代码只是将日期的打印延迟了2秒。它仍将保持3秒的间隔。

    例如:开始日期x:

    没有线程。睡眠,您将在以下位置打印:

    x, x + 3, x + 6, x + 9
    

    x + 2, x + 3 + 2, x + 6 + 2, x + 9 + 2
    

    等于:

    x + 2, x + 5, x + 8, x + 11 etc
    

    参见文档 https://docs.oracle.com/javase/8/docs/api/java/util/Timer.html

    对应于每个计时器对象的是一个后台线程 用于按顺序执行计时器的所有任务。计时器任务 应该很快完成。如果计时器任务花费过多时间 完成后,它将“占用”计时器的任务执行线程。这个可以,在 反过来,延迟后续任务的执行,可能会“扎堆” 当(如果)有问题的任务发生时,快速地连续执行 终于完成了。

    相同的线程将用于处理计时器任务的每次执行。当任务运行并且在计时器触发任务的下一次执行之前未及时完成时,下一次执行将延迟到上一次执行完成。该行为类似于线程池大小为1的ScheduledThreadPoolExecutor。