完全独立于系统时间变化的Java调度程序 [英] Java scheduler which is completely independent of system time changes
问题描述
使用Java Timer,然后切换到ScheduledExecutorService,但我的问题没有解决.因为在系统时间更改(通过 ntpd)之前安排的任务不会在指定的延迟时间执行.没有日志,因为什么都没有发生:(.
Was using Java Timer, Then switched to ScheduledExecutorService, but my problem is not fixed. As Tasks scheduled before system time change (through ntpd) are not executed on delay specified. Have no logs for same as nothing happens :(.
在 64 位 linux 上的目标中使用 jre 1.6.0_26 64 位.
using jre 1.6.0_26 64 bit in my target on 64 bit linux.
更新: ScheduledExecutorService 在 Windows 上运行良好.问题仅出现在运行 64 位 JVM 的基于 64 位 Linux 的系统上.它工作正常在64 位 linux 运行 32 位 JVM ......奇怪.也没有在任何博客上找到任何相同的参考.
Update: ScheduledExecutorService works fine on Windows. Problem is only on 64 bit Linux based system running 64 bit JVM. It works fine on 64 bit linux running 32 bit JVM...strange. Have not found any reference of same on any blogs either.
IBM 的 JAVA SDK 也有同样的问题(ibm-java-sdk-7.0-0.0-x86_64-archive.bin).
IBM's JAVA SDK has same problem (ibm-java-sdk-7.0-0.0-x86_64-archive.bin).
我已经提交了针对 JDK 7139684的缺陷,它被接受了,但已经被接受关闭和6900441 的标记重复.请投票给它,如果你觉得修复它是值得的......我不知道为什么它在几年多以来没有被修复
I had filed defect against JDK 7139684,It was accepted but has been closed and marked duplicate of 6900441. Please vote for it , if you feel its worth to get it fixed... I have no idea why its not been fixed since more than couple of years
这是我用来测试这个问题的示例代码:
Here is sample code I used to test this issue:
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);
}
}
推荐答案
有 JVM 中的 bug 在 Sytem 时间期间的整体调度向后更改,这也影响了非常基本的 Object.wait &Thread.sleep 方法.当系统时间切换甚至几秒钟时,保持 Java App 运行变得太冒险了.你永远不知道你的 Java 应用程序最终会变成什么.
There is bug in JVM for overall scheduling during Sytem time changes backward, which also impacts very basic Object.wait & Thread.sleep methods. It becomes too risky to keep Java App running when system time switches back by even certain seconds. You never know what your Java App will end up to.
所以我们决定:
- 编写看门狗脚本(非 Java :))来检查时间变化.
- 如果时间倒退一定数量,请关闭并重新启动 Java 应用程序.
另一种可能性是迁移到 32 位 JVM,但我们使用的是 JNI,然后目标平台上使用的本机库与 32 位不兼容.同样根据我们的经验,32 位 JVM 将我们的目标限制为 1.6G 堆,这对我们来说根本不够.
Another possibility was to move to 32bit JVM, But we are using JNI and then native libraries used on target platform are not 32bit compatible. Also from our experience 32bit JVM limits our target to 1.6G heap, which is not at all sufficient for us.
我知道我们的解决方案不是最优雅的解决方案,但在 JVM 修复或找到更好的解决方案之前,似乎没有其他方法.
I know ours is not most elegant solution, but untill JVM is fixed or some better solution is found, there doesn't seem to be any other way.
已除了上述解决方案外,我们还在考虑 Chris 的第一个建议:
Edited: We are also considering 1st suggestion from Chris in addition to above solution:
- 将 NTP 配置为永远不会有大的时间跳跃.只消磨时间慢慢地.仅在停机期间手动应用大时间跳跃.
这篇关于完全独立于系统时间变化的Java调度程序的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!