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

发布于 2024-12-29 06:00:56 字数 1724 浏览 1 评论 0原文

原来使用Java Timer,然后改用ScheduledExecutorService,但我的问题没有解决。 由于在系统时间更改之前(通过 ntpd)计划的任务不会按指定的延迟执行。没有日志,就像没有发生一样:(。

在 64 位 Linux 上的目标中使用 jre 1.6.0_26 64 位。

更新: ScheduledExecutorService 在 Windows 上运行良好。问题仅出现在运行 64 位 JVM 的 64 位 Linux 系统上。效果很好 在 64 位 Linux 运行 32 位 JVM...奇怪。在任何博客上也没有找到任何相同的参考。

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);
    }

}

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 :(.

using jre 1.6.0_26 64 bit in my target on 64 bit linux.

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's JAVA SDK has same problem
(ibm-java-sdk-7.0-0.0-x86_64-archive.bin).

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);
    }

}

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(2

月依秋水 2025-01-05 06:00:56

在系统时间向后更改期间,JVM 中存在JVM 的错误,这也导致了总体调度影响非常基本的 Object.wait & Thread.sleep 方法。当系统时间切换回特定秒数时,保持 Java 应用程序运行就变得风险太大。你永远不知道你的 Java 应用程序最终会变成什么样子。

所以我们决定:

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

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

我知道我们的解决方案不是最优雅的,但是在修复 JVM 或找到更好的解决方案之前,似乎没有其他方法。

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

  • 配置 NTP,使其永远不会出现大的时间跳跃。只能消磨时间
    慢慢地。仅在停机期间手动应用大时间跳跃。

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.

So we have decided to:

  • Write watch dog script (non Java :)) to check time change.
  • if time switches back by certain amount, shutdown and restart Java app.

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.

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.

Edited:
We are also considering 1st suggestion from Chris in addition to above solution:

  • Configure NTP to never have a big time jump. Only slew the time
    slowly. Only apply big time jumps manually during downtime.
江挽川 2025-01-05 06:00:56

我曾针对同样的问题进行过研究,但尚未找到解决方案。我研究了 Quartz 和所有内置的 JRE 方法。纳米时间方法可能使用每个 CPU 的单调时钟,但我相信,如果线程迁移到另一个 CPU,您将面临大跳跃的风险。我的结论如下:

  1. 将 NTP 配置为永远不会出现较大的时间跳跃。只能慢慢消磨时间。仅在停机期间手动应用大时间跳跃。
  2. 使用多个较短的超时,并且需要两次超时才能声明远程计算机死亡。如果您本身只有一个系统计时,这将无济于事,但可以帮助多个系统
  3. 故意使用远程计算机向您发送定期唤醒。如果你自己的时钟在两次醒来之间倒退,那么你就知道你所有的计时器都会延迟启动。

基本上,这是一个巨大的痛苦,但没有灵丹妙药。

I worked against the same problem and have not found a solution. I looked at Quartz and all of the built-in JRE methods. The nanotime methods may use per-CPU monotonic clocks, but you risk big jumps if the threads are migrated to another CPU, I believe. My conclusions were the following:

  1. Configure NTP to never have a big time jump. Only slew the time slowly. Only apply big time jumps manually during downtime.
  2. Use multiple shorter timeouts, and require two timeouts to declare a remote machine dead. This won't help if you have just one system timing itself, but can help with multiple systems
  3. use a remote machine on purpose to send you periodic wakeups. If your own clock goes backward between wakeups, then you know all of your timers are going to fire late.

Basically, this is a huge pain but there are no silver bullets.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文