我只有一个程序用于在它自己的线程中执行此操作:
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();
}
}
}
基本上我在这样循环时总是被教导睡觉,所以我做了,我的程序至少睡了5毫秒,或者它可以睡觉的最长时间而不超过限制(1/30秒)。但我正在四处看书,睡觉听起来不是很好。
从他说的话来看,如果它太接近睡眠下限,我的程序甚至都不会睡觉,等等。当system.printing时间变化时,变化的范围大约是.31508 - .03475,这对我来说非常好,因为我的程序会导致不准确。
话虽如此,我还能做些什么呢?我正在考虑添加类似这样的东西,而不是尝试{Sleep}:
long waitTill = (long) (System.nanoTime()+lastTime/1000000000f),
now = System.nanoTime();
while(now < waitTill){
now = System.nanoTime();
}
但我的线程不会占用相同数量的处理器时间吗?我认为重点是阻止我们的线程占用更多的处理器而不是实际需要..
那么,我应该使用睡眠(最小睡眠时间更长?),我应该使用我的替代方案,我应该使用其他替代方案,还是应该让我的程序以无限制的速度循环?即使我考虑到睡眠不准确,我的编程也很差吗?
感谢您的帮助!
修改 因此,定时器已被推荐,但我明白,如果我的任务没有在Timer再次调用之前完成,那么我会遇到问题。这对我的计划来说是一个明确的问题。我觉得我已经通过使用delta处理了Thread.sleep()的问题,那么Thread.sleep()会像以前那样更好吗?
答案 0 :(得分:5)
要解决此问题,您需要重新考虑您的设计。基本上你正在做的是定期安排工作。运行/静止/睡眠模式有效,但正如您的研究发现的不是最佳解决方案。
现代语言具有“任务运行”模式,允许编程环境/操作系统更好地管理任务的执行。
在Java中,有java.util.timer和java.util.timertask。使用任务运行模式,您可以创建任务,并将其安排为以特定间隔运行。
通过取消计时器,计时器还为您提供了一种更简洁的方法来停止执行循环,而不是设置布尔标志。
来自评论:
有一些人应该注意的问题。如果您的任务是任务运行时间超过计划间隔的任务,则可以在上一个任务仍在执行时运行另一个任务。一些解决方案:
另一个常见问题是计划的计时器通常是尽力而为。也就是说,OS / Framework尝试按计划运行任务,但不保证任务将在指定的时间间隔内完全执行。因此,如果您的任务需要严格的确定性调度,您可能需要更接近操作系统/硬件解决方案。
答案 1 :(得分:1)
你绝对应该避免纯粹旋转(你的第二个例子)(除了某些特定用例,例如同步原语),因为它消耗CPU 只做等待而且很容易导致死锁!
这就是为什么你经常使用 sleep 延迟消耗更少的CPU并为其他线程提供更多工作机会,从而降低死锁的风险。
只要你知道自己在做什么,你的第一个循环就没有问题。
但您应该更喜欢专用于这类用例的组件:计时器。
答案 2 :(得分:0)
正如Alan和Pragmateek都说的那样,Timers通常比使用Thread.sleep()更受欢迎,但正如Martin James所说的那样“Sleep()肯定会被滥用,而且经常会被误用,但这并不会使它本质上不正确或某种反模式“。
我的结论是,由于我使用delta,我处理Thread.sleep()的不准确。话虽如此,使用它没有问题。计时器实现起来会有点困难,因为我的任务需要在再次调用计时器之前完成,这对我的程序来说将非常难以保证。
因此,在这个应用程序中,以及我使用它的方式,Thread.sleep()是一个非常可行的选项。
答案 3 :(得分:0)
而不是sleep(),最好使用wait()和notify()。
当使用sleep()时,线程退出正在运行的队列并再次运行该线程,OS已经做了一些额外的工作,这是一个纯粹的开销。
但是当线程正在等待时,它不会退出正在运行的队列,因此没有开销。
答案 4 :(得分:0)
当提出问题时,如果计时器任务的时间超过间隔,计时器的行为如何。
我编写了一个愚蠢的示例程序来观察计时器的行为:
public class FlawedTimerTask extends TimerTask {
final int taskId;
final long sleepTime;
int counter = 0;
public FlawedTimerTask(int taskId, long sleepTime) {
super();
this.taskId = taskId;
this.sleepTime = sleepTime;
}
@Override
public void run() {
long beginTimeInNs = System.nanoTime();
System.out.println("taskId=" + taskId + ", run=" + counter + ", beginning at " + (beginTimeInNs-beginOfExperiment));
try {
Thread.sleep(sleepTime);
} catch (InterruptedException e) {
e.printStackTrace();
}
long endTimeInNs = System.nanoTime();
System.out.println("taskId=" + taskId + ", run=" + counter + ", ending at " + (endTimeInNs-beginOfExperiment));
counter++;
}
static long beginOfExperiment;
public static void main(String[] args) {
beginOfExperiment = System.nanoTime();
Timer timer = new Timer();
timer.schedule(new FlawedTimerTask(1, 800), 500, 500);
timer.schedule(new FlawedTimerTask(2, 1000), 500, 2500);
}
}
输出结果为:
taskId=1, run=0, beginning at 491988762
taskId=1, run=0, ending at 1291944877
taskId=2, run=0, beginning at 1292056514
taskId=2, run=0, ending at 2293928680
taskId=1, run=1, beginning at 2294036467
taskId=1, run=1, ending at 3094967160
taskId=1, run=2, beginning at 3095097404
taskId=1, run=2, ending at 3894902745
taskId=1, run=3, beginning at 3895045820
taskId=1, run=3, ending at 4695902088
taskId=2, run=1, beginning at 4696095849
taskId=2, run=1, ending at 5695887973
taskId=1, run=4, beginning at 5695991911
taskId=1, run=4, ending at 6496896941
taskId=1, run=5, beginning at 6497002803
taskId=1, run=5, ending at 7297814161
taskId=1, run=6, beginning at 7297998297
taskId=1, run=6, ending at 8098803239
taskId=2, run=2, beginning at 8098922575
taskId=2, run=2, ending at 9098814787
taskId=1, run=7, beginning at 9098971977
taskId=1, run=7, ending at 9899803866
taskId=1, run=8, beginning at 9899970038
taskId=1, run=8, ending at 10699807458
taskId=1, run=9, beginning at 10699912038
taskId=1, run=9, ending at 11500693882
taskId=2, run=3, beginning at 11500815143
taskId=2, run=3, ending at 12501656270
taskId=1, run=10, beginning at 12501781380
taskId=1, run=10, ending at 13302714640
taskId=1, run=11, beginning at 13302888511
taskId=1, run=11, ending at 14102727215
taskId=1, run=12, beginning at 14102929958
taskId=1, run=12, ending at 14903695762
taskId=2, run=4, beginning at 14903878616
taskId=2, run=4, ending at 15903607223
taskId=1, run=13, beginning at 15903775961
taskId=1, run=13, ending at 16705705613
taskId=1, run=14, beginning at 16705798644
taskId=1, run=14, ending at 17505650180
taskId=1, run=15, beginning at 17505881795
taskId=1, run=15, ending at 18306578307
taskId=2, run=5, beginning at 18306718815
taskId=2, run=5, ending at 19306666847
taskId=1, run=16, beginning at 19306757953
taskId=1, run=16, ending at 20107480129
taskId=1, run=17, beginning at 20107580217
taskId=1, run=17, ending at 20907534407
taskId=1, run=18, beginning at 20907640911
taskId=1, run=18, ending at 21709616117
taskId=2, run=6, beginning at 21709784855
taskId=2, run=6, ending at 22709563506
taskId=1, run=19, beginning at 22709664236
taskId=1, run=19, ending at 23510559642
taskId=1, run=20, beginning at 23510653956
taskId=1, run=20, ending at 24310465713
taskId=1, run=21, beginning at 24310572217
taskId=1, run=21, ending at 25111451583
taskId=2, run=7, beginning at 25111549105
taskId=2, run=7, ending at 26111453508
taskId=1, run=22, beginning at 26111544614
taskId=1, run=22, ending at 26913489022
taskId=1, run=23, beginning at 26913629531
taskId=1, run=23, ending at 27713421398
taskId=1, run=24, beginning at 27713577305
taskId=1, run=24, ending at 28514443839
taskId=2, run=8, beginning at 28514550985
taskId=2, run=8, ending at 29514349525
taskId=1, run=25, beginning at 29514496450
taskId=1, run=25, ending at 30315367475
taskId=1, run=26, beginning at 30315469488
taskId=1, run=26, ending at 31115349896
taskId=1, run=27, beginning at 31115475648
taskId=1, run=27, ending at 31917465609
taskId=2, run=9, beginning at 31917563773
taskId=2, run=9, ending at 32917368087
taskId=1, run=28, beginning at 32917524636
taskId=1, run=28, ending at 33718337276
taskId=1, run=29, beginning at 33718481634
taskId=1, run=29, ending at 34518366533
taskId=1, run=30, beginning at 34518459564
taskId=1, run=30, ending at 35319336363
taskId=2, run=10, beginning at 35319516009
taskId=2, run=10, ending at 36319338930
taskId=1, run=31, beginning at 36319440301
taskId=1, run=31, ending at 37121299378
taskId=1, run=32, beginning at 37121403957
taskId=1, run=32, ending at 37921223413
taskId=1, run=33, beginning at 37921324785
taskId=1, run=33, ending at 38722168863
taskId=2, run=11, beginning at 38722270877
taskId=2, run=11, ending at 39722259328
你可以观察到