17

Javaタイマーを使用していた後、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);
    }

}
4

2 に答える 2

7

JVMには、システム時間の逆方向変更中の全体的なスケジューリングに関するバグがあり、非常に基本的な Object.wait および Thread.sleep メソッドにも影響します。システム時間が特定の秒単位で戻った場合でも、Java アプリを実行し続けるのは非常に危険です。Java アプリケーションが最終的にどうなるかはわかりません。

そのため、次のことを決定しました。

  • 時刻の変更を確認するためのウォッチドッグ スクリプト (非 Java :)) を記述します。
  • 時間が一定量戻った場合は、Java アプリをシャットダウンして再起動します。

もう 1 つの可能性は 32 ビット JVM に移行することでしたが、JNI を使用しているため、ターゲット プラットフォームで使用されるネイティブ ライブラリは 32​​ ビット互換ではありません。また、私たちの経験から、32 ビット JVM はターゲットを 1.6G ヒープに制限しますが、これは私たちにとってまったく十分ではありません。

私たちのソリューションが最も洗練されたソリューションではないことはわかっていますが、JVM が修正されるか、より優れたソリューションが見つかるまで、他の方法はないようです。

編集済み: 上記のソリューションに加えて、クリスからの最初の提案も検討しています:

  • 大幅な時間のジャンプがないように NTP を構成します。ゆっくりと時間をつぶしただけです。ダウンタイム中にのみ手動で大きなタイム ジャンプを適用します。
于 2012-02-01T05:46:02.853 に答える
2

私は同じ問題に取り組みましたが、解決策が見つかりませんでした。Quartz とすべての組み込み JRE メソッドを調べました。nanotime メソッドは CPU ごとの単調クロックを使用する場合がありますが、スレッドが別の CPU に移行されると、大きなジャンプが発生するリスクがあると思います。私の結論は次のとおりです。

  1. 大幅な時間のジャンプがないように NTP を構成します。ゆっくりと時間をつぶしただけです。ダウンタイム中にのみ手動で大きなタイム ジャンプを適用します。
  2. 複数の短いタイムアウトを使用し、リモート マシンの停止を宣言するには 2 つのタイムアウトが必要です。これは、システムのタイミング自体が 1 つしかない場合は役に立ちませんが、複数のシステムでは役立ちます。
  3. 意図的にリモート マシンを使用して、定期的なウェイクアップを送信します。ウェイクアップの間に自分の時計が逆行すると、すべてのタイマーが遅れて起動することがわかります。

基本的に、これは大きな苦痛ですが、特効薬はありません。

于 2012-01-28T13:46:38.843 に答える