使用循环在新线程中运行我的程序 - 不要使用睡眠?

csg*_*000 2 java multithreading sleep loops

我只有一个程序,用于在它自己的线程中执行此操作:

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();
        }
    }
}
Run Code Online (Sandbox Code Playgroud)

基本上我总是在这样循环时被教导睡觉,所以我做了,我的程序睡眠至少5毫秒,或者它可以睡觉的最多时间而不超过限制(1/30秒).但我正在四处看书,睡觉听起来不是很好.

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

从他的说法来看,如果它太接近睡眠下限,我的程序甚至都不会睡觉,等等.当system.printing时间的变化时,变化的范围大约是.31508 - .03475,这对我来说真的很好,因为我的程序会导致不准确.

话虽这么说,我还能做些什么呢?我正在考虑添加类似这样的东西,而不是尝试{Sleep}:

long waitTill = (long) (System.nanoTime()+lastTime/1000000000f), 
    now = System.nanoTime();
while(now < waitTill){
    now = System.nanoTime();
}
Run Code Online (Sandbox Code Playgroud)

但是我的线程不会占用相同数量的处理器时间吗?我认为重点是阻止我们的线程占用更多的处理器,而不是实际需要的...

那么,我应该使用睡眠(最小睡眠时间更长?),我应该使用我的替代方案,我应该使用其他替代方案,还是应该让我的程序以无限制的速度循环?即使我考虑到睡眠不准确,我编程也很差吗?

谢谢您的帮助!

编辑: 所以,定时器已被推荐,但我明白,如果我的任务没有在Timer再次调用之前完成,那么我会遇到问题.这对我的计划来说是一个明确的问题.我觉得我已经通过使用delta处理了Thread.sleep()的问题,所以,Thread.sleep()会像以前一样更好吗?

Ala*_*lan 5

要解决此问题,您需要重新考虑您的设计.基本上你正在做的是定期安排工作.运行/静止/睡眠模式有效,但正如您的研究发现的不是最佳解决方案.

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

在Java中有java.util.timer以及java.util.timertask.使用任务运行模式,您可以创建任务,并将其安排为以特定间隔运行.

通过取消定时器而不是设置布尔标志,定时器还为您提供了一种更简洁的方法来停止执行循环.

来自评论:

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

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

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

  • 你必须确保你的任务在这段时间内完成(许多人经常忘记这一点).否则会出现严重问题,必须使用Thread.sleep代替变量间隔. (3认同)