【问题标题】:Correct Clock to improve Accuracy in Java正确的时钟以提高 Java 中的准确性
【发布时间】:2014-07-01 07:58:36
【问题描述】:

我想创建一个基本上像普通时钟一样工作的 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 毫秒。 我忘记了一些基本的东西还是我的方法错误?如果您能告诉我一种更高效的方法,那也太好了?

【问题讨论】:

  • 你的问题到底是什么?
  • 如果您尝试基于sleep() 生成可靠的时钟,那么您是从错误的方向解决问题。使用sleep(),但在每个刻度上测量从您的开始时间经过的时间,并根据经过的时间更新您的时钟。
  • 我的问题在帖子的最后。如果我的方法是错误的或者是否有更好的方法?因为我的结果与我对该主题的研究表明的相反。

标签: java performance time


【解决方案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 是提前计算出来的(基本上,你一开始只看当前时间)。

【讨论】:

  • 这不会阻止sleep 睡眠太长。对于sleep(1) 之类的东西,必须假设它可能会休眠 5 毫秒甚至 10 毫秒......(我也没有解决方案,除了一些忙于等待 System.nanotime() ......毫秒精确的时间很难用Java实现...)
  • @Marco13 如果您的计算机受 CPU 限制并且没有任何移动,那么在某些情况下您可能永远无法获得所需的精度。最好现在打印时间。
  • @Marco13 AFAIK,在这个方向上没有什么可以帮助的。 AFAIK 假设 1. 核心是免费的,2. 时间分辨率足够,3. 系统没有过载,否则不会花费更长的时间。 nanotime 忙等待是个好主意。
猜你喜欢
  • 1970-01-01
  • 2020-06-15
  • 1970-01-01
  • 2021-01-13
  • 1970-01-01
  • 2018-05-21
  • 2016-04-02
  • 2021-06-30
  • 2014-08-05
相关资源
最近更新 更多