我只有一个程序曾经在自己的线程中执行此操作:

public void run(){
    long lastTime = System.nanoTime();
    float lastSleep = 0;
    //Everything is in seconds.
    while(running){
        float delta = (System.nanoTime()-lastTime)/1000000000f;
        lastTime = System.nanoTime();
        manager.update(delta);
        panel.repaint();
        lastSleep = Math.max(maxTicSpeed-(delta-lastSleep),5/1000f);
        try{
            Thread.sleep((long) Math.round(lastSleep*1000));
        }catch(InterruptedException e){
            e.printStackTrace();
        }
    }
}

基本上,总是这样循环学习 sleep ,所以我做到了,我的程序至少 sleep 了5毫秒,或者它在不超过限制的情况下最多可以 sleep 的时间(1/30秒)。但是我正在四处看书,而且 sleep 听起来并不好。

http://msmvps.com/blogs/peterritchie/archive/2007/04/26/thread-sleep-is-a-sign-of-a-poorly-designed-program.aspx

从他的话看来,如果我的程序太接近 sleep 下限等,我的程序甚至不会休眠。系统打印时间更改时,更改范围大约为.31508-.03475,这对我来说确实足够,因为我的程序考虑到了不准确性。

话虽这么说,我该怎么办呢?我正在考虑添加这样的内容,而不是try {Sleep}:
long waitTill = (long) (System.nanoTime()+lastTime/1000000000f),
    now = System.nanoTime();
while(now < waitTill){
    now = System.nanoTime();
}

但是我的线程会不会仍然占用相同数量的处理器时间?我认为关键是要阻止我们的线程占用过多的处理器,而不是实际需要的。

因此,我应该使用sleep(具有更长的最小 sleep 时间吗?),应该使用我的替代方法,还是应该使用其他替代方法,还是让我的程序以不受限制的速度循环?即使我解释了 sleep 不正确,我的编程能力还是很差吗?

谢谢您的帮助!

编辑:
因此,建议使用Timers,但是我知道,如果在Timer再次调用之前我的任务没有完成,那么我会遇到问题。这是我程序的确定关注点。我觉得我已经通过使用增量解决了Thread.sleep()的问题,所以,像以前一样Thread.sleep()会更好吗?

最佳答案

为了解决此问题,您将需要重新考虑您的设计。本质上,您正在做的是按定期计划的时间间隔进行工作。运行/同时运行/ sleep 模式有效,但是您的研究发现并非最佳解决方案。

现代语言具有“任务运行”模式,该模式允许编程环境/OS更好地管理任务的执行。

在Java中,有java.util.timerjava.util.timertask。使用任务运行模式,您可以创建任务,并将其计划为以一定间隔运行。

计时器还可以通过取消计时器(而不是设置 boolean 标志)来提供一种更干净的方式来停止执行循环。

从评论:

应该注意几个问题。如果您的任务是某个任务的运行时间可能超过计划的时间间隔,则有可能在上一个任务仍在执行时运行另一个任务。一些解决方案:

  • 使用作业队列来排队要完成的工作。如果队列中没有任何工作,则任务返回。
  • 在javascript中常见的另一种方法是安排任务一次执行,并在任务结束时重新安排该任务一次执行。
  • 一种不太优雅的方法,使用标志指示正在执行的特定任务。这可行,但是需要您正确管理标志的状态,这很容易出错。

  • 另一个常见的问题是计划的计时器通常是尽力而为的。也就是说,OS/Framework尝试按计划运行任务,但不保证任务将完全按照指定的间隔执行。因此,如果您的任务需要严格的确定性计划,则可能需要更接近操作系统/硬件的解决方案。

    10-07 18:56
    查看更多