正确的时钟提高Java的准确性

时间:2014-07-01 07:58:36

标签: java performance time

我想创建一个基本上像普通时钟一样工作的MIDI时钟。它只是勾选并计算其刻度。现在我已经阅读了很多次Thread.sleep()根本不准确。因此,每隔几个周期校正一次,确保它长期稳定吗?

我的时钟课

public class Clock implements Runnable {

   long beatsPassed = 0; 
   double bpm = 120;       // default
   double beatLength;   // default
   boolean running = false;

   Clock(int bpm) {
       this.bpm = bpm;
       this.beatLength = 60.0 / bpm;
       this.running = true;
   }

   public void run() {

       int beatLengthInMS = (int) (this.beatLength * 1000);
       long baseTime = System.currentTimeMillis();
       // long corrected = 1;

       try {

           while (running) {

               // check delay every 9 beats
               // mod == 0 lets it the first time through which causes a negative timeout
               if (this.beatsPassed % 10 == 9) {
                   // corrected = (System.currentTimeMillis() - baseTime) - (beatLengthInMS * 9);
                   Thread.sleep(beatLengthInMS + ((System.currentTimeMillis() - baseTime) - (beatLengthInMS * 9)));
                   baseTime = System.currentTimeMillis();

               } else {
                   Thread.sleep(beatLengthInMS);
               }

               this.beatsPassed++;
               // System.out.println(corrected);
           }

       } catch (InterruptedException e) {
           e.printStackTrace();
       }
   }
}

现在我已经测量了相当稳定的时间。它总是增加约6-9毫秒。 我忘了一些基本的东西还是我的方法错了?如果你能告诉我一个更高效的方式,这也很棒吗?

1 个答案:

答案 0 :(得分:1)

最简单的方法(除了使用Timer,在JDK中有两个AFAIK)是一种方法

void sleepUntil(long absoluteTime) throw InterruptedException {
    while (true) {
        long now = System.currentTimeMillis();
        if (now >= absoluteTime) break;
        Thread.sleep(absoluteTime - now);
    }
}

使用循环是因为虚假的唤醒(在实践中可能永远不会发生,但比抱歉更安全)。预先计算absoluteTime(基本上,你只看一开始的当前时间)。