Java - 替代 thread.sleep

Posted

技术标签:

【中文标题】Java - 替代 thread.sleep【英文标题】:Java - alternative to thread.sleep 【发布时间】:2012-02-26 23:02:55 【问题描述】:

我需要将 while 循环暂停特定的毫秒数。我曾尝试使用 Thread.sleep(duration) 但它不准确,尤其是在循环场景中。毫秒精度在我的程序中很重要。

这是在expectedElapsedTime 过去之前我不想回去检查条件的算法。

while (condition) 
    time = System.currentTimeMillis();
    //do something
    if (elapsedTime(time) < expectedElapsedTime) ) 
        pause the loop  // NEED SUBSTITUTE FOR Thread.sleep()
    
    // Alternative that I have tried but not giving good results is 
    while ((elapsedTime(time) < expectedElapsedTime)) 
        //do nothing
    


long elapsedTime(long time) 
   long diff = System.currentTimeMillis() - time;
   return diff;

【问题讨论】:

***.com/questions/3976344/… 【参考方案1】:

试试ScheduledThreadPoolExecutor。它应该提供更可靠的计时结果。

【讨论】:

这是现在推荐的方式(Java 6)。这样您就不需要进行连续轮询,也不需要使用 while 循环。然后将需要定期运行的代码放入 Runnable 对象中。 使用 ScheduledThreadPoolExecutor 如何帮助他暂停他的 while 循环? 它没有,但它解决了以准确的间隔进行工作的真正需求。 感谢您的建议。我会试试看。 @LuisA.Florit 我不确定你在问什么。也许你应该提交一个问题?【参考方案2】:

你期待什么?

如果您进入睡眠状态,那么一旦您的进程再次可运行,它将不得不等待线程调度程序再次对其进行调度。

我的意思是,如果你进入睡眠状态 50 秒,这并不意味着你的进程将在 50 秒内运行。因为它会唤醒并且可以运行,所以它必须等待被调度到 CPU,这需要额外的时间加上你有上下文切换的时间。

您无法控制它,因此您无法达到您所说的准确性。

对于您的情况,我建议改为使用旋转循环。

long now = System.currentTimeMillis();   
while(now < expectedElapsedTime)
    now = System.currentTimeMillis();

【讨论】:

根据我的理解,这不会给出 100% 的准确率,对吧?做一个不同的线程来处理它不是更好吗? @aleroot:是的,当然会浪费周期。但无论如何它不会持续很长时间。他说毫秒 @warbio:No.Another thread is no option as you have the overhead of context switch (at the very list) 正如我在原始代码帖子中提到的,我尝试过这个选项,它比 Thread.sleep 提供了更好的结果,但它确实有点偏离了几次。 好吧,你不能拥有这一切。对不起。要么你做某种sleepwait,这意味着你让出CPU,因此你的线程不受CPU限制,你看不到你说的那个尖峰,但是你不能以毫秒为单位获得你需要的准确度(在你放弃 CPU 之后,你无法准确控制何时取回它——这是不可能的)或者你使用轮询并拥有线程受 CPU 限制并且 CPU 不断工作,但是由于您不放弃 CPU,因此您具有尽可能高的准确度,但您会遇到您抱怨的尖峰。看看您愿意接受哪种权衡【参考方案3】:

Java 不是一个实时系统,你不能让一个线程在如此紧张的时间里离开并回来。要将程序执行时间安排到毫秒级,您需要使用不同的平台——例如simpleRTJ 或Java Real-Time extension。

【讨论】:

【参考方案4】:

延迟很可能是任意选择的,所以我会质疑您是否需要实时间隔计时。

如果您需要阅读时间,您需要忙于等待时间到达。放弃 CPU 意味着你不能保证你会在你想要的时候把它拿回来。

【讨论】:

【参考方案5】:

您可以实现等待/通知机制,并委托另一个线程负责通知处于等待状态的另一个线程该时间已过并且它可以继续...

例如,当线程A需要等待一定时间时,您可以将线程置于等待状态并启动一个定时器任务,在一定时间(间隔)后调用通知并唤醒继续前进的线程A ,这可能是另一种选择。

【讨论】:

如果线程 waits 处于阻塞状态。这意味着上下文切换,这意味着额外的时间,据我了解,他确实需要严格的精度 这可能是另一种选择,我不知道它是否更准确,应该测试...... 我试过 this.wait(millisec,nanosec) ,不比 Thread.sleep 好。 另外,我阅读了 ***.com/questions/824110/… 中建议的使用守护线程的解决方案。 另外,我阅读了***.com/questions/824110/…中建议的使用守护线程的解决方案。【参考方案6】:

如果您想要准确地处理声音,您可以使用音序器并在 BPM 中设置速度: sequencer.setTempoInBPM(120);

【讨论】:

【参考方案7】:

解决方案是使用可运行的处理程序并使用“postDelayed”方法。示例:

new Handler().postDelayed(new Runnable() 
public void run () 
    // Do delayed stuff!

, 5000L); //5 seconds delay 

https://***.com/a/21680858

【讨论】:

【参考方案8】:

不要忘记垃圾收集器暂停。它可以打败你所有的计划

【讨论】:

以上是关于Java - 替代 thread.sleep的主要内容,如果未能解决你的问题,请参考以下文章

替代 Thread.Sleep

使用 Thread.Sleep 等待的替代方法

c#中怎样建立定时器?用以替代thread.sleep(),克服sleep延时不精确的问题。

Java:关于Thread.sleep()

java Thread.sleep卡死问题

为啥 Thread.Sleep 如此有害