Java调度程序完全独立于系统时间的变化

YoK*_*YoK 17 java timer scheduler ntp 32bit-64bit

使用Java Timer,然后切换到ScheduledExecutorService,但我的问题没有修复.在系统时间更改之前安排的任务(通过ntpd)不会在指定的延迟时执行.没有任何日志记录:(.

在64位linux上使用我的目标中的jre 1.6.0_26 64位.

更新: ScheduledExecutorService在Windows上运行正常.问题仅出在运行64位JVM的基于64位Linux的系统上.它在运行32位JVM的64位linux上运行良好......很奇怪.在任何博客上都没有找到任何相同的参考.

IBM的JAVA SDK也存在同样的问题(ibm-java-sdk-7.0-0.0-x86_64-archive.bin).

我已经提交了针对JDK 7139684的缺陷,它被接受但已被关闭并标记为 6900441的副本.请投票给它,如果你觉得它的价值得到修复...我不知道为什么它已经修复了几年以上

以下是我用来测试此问题的示例代码:

package test;

import java.io.IOException;
import java.util.Date;
import java.util.concurrent.Executors;
import java.util.concurrent.ScheduledExecutorService;
import java.util.concurrent.TimeUnit;

/**
 * @author yogesh
 *
 */
public class TimerCheck  implements Runnable {

    ScheduledExecutorService worker;


    public TimerCheck(ScheduledExecutorService worker) {
        super();
        this.worker = worker;
        this.worker.schedule(this, 1, TimeUnit.SECONDS);
    }

    private static void update() {
        System.out.println("TimerCheck.update() "+new Date(System.currentTimeMillis()));
    }

    @Override
    public void run() {
            update();
            worker.schedule(this, 1, TimeUnit.SECONDS);
    }

    /**
     * @param args
     */
    public static void main(String[] args) {
        ScheduledExecutorService worker = Executors.newScheduledThreadPool(1);
        new TimerCheck(worker);
    }

}
Run Code Online (Sandbox Code Playgroud)

YoK*_*YoK 7

臭虫在JVM的过程中系统正时总计划更改落后,这也影响非常基本的Object.wait及的Thread.sleep方法.当系统时间切换回甚至几秒钟时,保持Java App运行变得太冒险.你永远不知道你的Java应用程序最终会是什么.

所以我们决定:

  • 写看门狗脚本(非Java :))来检查时间变化.
  • 如果时间切换回一定量,关闭并重新启动Java应用程序.

另一种可能性是转移到32位JVM,但我们使用的是JNI,然后在目标平台上使用的本机库不兼容32位.另外根据我们的经验,32位JVM将我们的目标限制在1.6G堆,这对我们来说根本不够.

我知道我们不是最优雅的解决方案,但直到JVM被修复或找到了更好的解决方案,似乎没有任何其他方式.

编辑: 除了上述解决方案之外,我们还在考虑克里斯的第一个建议:

  • 配置NTP永远不会有大的时间跳跃.只能慢慢地浪费时间.仅在停机期间手动应用大时间跳转.