如何在Android中减少Thread.sleep()延迟
我在Android应用程序中(非UI)线程的循环中生成计时事件,我需要这些事件以精确的时间间隔发生(精确在这里意味着变化不超过+/-5毫秒)。任何+/-10毫秒(当然+/-20毫秒)的误差都可以被用户感知到。在这个循环的顶部,我做了一些其他的计算,这些计算花费了可变的时间,但是在循环的底部,我需要事件在预先计算的时间发生 我的非UI线程的一次尝试的高度简化版本(无异常处理)如下所示:如何在Android中减少Thread.sleep()延迟,android,multithreading,concurrency,latency,Android,Multithreading,Concurrency,Latency,我在Android应用程序中(非UI)线程的循环中生成计时事件,我需要这些事件以精确的时间间隔发生(精确在这里意味着变化不超过+/-5毫秒)。任何+/-10毫秒(当然+/-20毫秒)的误差都可以被用户感知到。在这个循环的顶部,我做了一些其他的计算,这些计算花费了可变的时间,但是在循环的底部,我需要事件在预先计算的时间发生 我的非UI线程的一次尝试的高度简化版本(无异常处理)如下所示: public final void run() { long loopTime = 2500L;
public final void run() {
long loopTime = 2500L;
long eventTime = (System.nanoTime() / 100000L) + loopTime;
while (true) {
calcutionsTakingVaryingAmountOfTime(); // takes 200 millisecs or less
long eventWait = eventTime - (System.nanoTime() / 100000L);
Thread.sleep(eventWait / 10L);
listener.onEvent();
eventTime = eventTime + loopTime;
}
}
对listener.onEvent()
的调用需要精确计时
在上面的示例中,定时变量loopTime
、eventTime
和eventWait
以十分之一毫秒为单位测量时间。测量当前时间的表达式(System.nanoTime()/100000L)
同样以十分之一毫秒为单位
我绝对肯定calculationVaringamountftime()
所需时间总是少于200毫秒,而调用listener.onEvent()
只需几毫秒。因此,当loopTime
设置为2500L
时,我的事件应该每250毫秒发生一次
我已输入代码(未显示)以打印到Log.d()
Thread.sleep()中的延迟时间。就是我计算
long latency = (System.nanoTime() / 100000L) - eventTime
从Thread.sleep()
返回后立即打印到Log.d()
当我在模拟器中运行它时,我发现延迟
(除以10以获得毫秒的结果)通常在循环的连续过程中在1到50毫秒之间跳跃,偶尔值高达半秒。在实际设备上运行时,情况会好一些,但仍然有点不稳定(即使如此,仿真器的行为也让我怀疑这是否会发生在用户的设备上)
为了稳定事件并控制延迟,我尝试了其他几种方法:
- 在中,将
调用替换为Thread.sleep(eventWait/10L)
(我知道wait()的用法完全不恰当)this.wait(eventWait/10L)
- 在进入循环之前,我操纵了线程优先级,调用了
like在所有android库中都是这样做的Process.setThreadPriority(Process.thread\u PRIORITY\u emergency\u AUDIO)
Thread.sleep()
调用:
while ((System.nanoTime() / 100000L) < eventTime)
;
while((System.nanoTime()/100000L)
一方面,我觉得像一个醉酒的水手在自由号上骑自行车很尴尬。另一方面,我开始认为没有更好的方法,我应该在轮询循环中燃烧机器周期,以减少延迟,并满足我的规范。当然,当我的应用程序转到后台时,我会暂停线程,这样轮询循环就可以工作了。但这真是浪费
如果您有任何想法,我们将不胜感激。我将使用带有
处理程序的延迟消息来实现类似目的。这可能有点过分。在你的情况下,我会看一看定时器
类
mTimer = new Timer();
mTimer.scheduleAtFixedRate(new TimerTask() {
@Override
public void run() {
Log.v("TEST", " tick");
}
}, 0, 250);
这给了我emulator的延迟+-2毫秒。谢谢你的建议。我试过几件事。首先,我尝试使用对“java.util.Timer.schedule(TimerTask,long delay)”的调用(或多或少)替代对“Thread.sleep()”的调用。我对你的建议有点怀疑。我试过几件事。首先,我尝试使用对“java.util.Timer.schedule(TimerTask,long delay)”的调用(或多或少)替代对“Thread.sleep()”的调用。然后我试着使用“scheduleAtFixedRate()”,就像你的一样。在这两种情况下,我在emulator上都有1到70毫秒的延迟,尽管延迟几乎符合设备的规格。你还做了什么来在模拟器上获得+/-2毫秒的延迟?我只运行了一个很小的测试应用程序,所以几乎没有压力。我的CPU是Intel(R)Core(TM)2 Duo CPU T9300@2.50GHz。谢谢回复。“这对我很有用。”歌词:我和你有同样的问题Thread.sleep()
破坏了我的应用程序,因为我还有和你描述的一样大的延迟。但是您是如何使用计时器模拟线程.sleep
?你已经找到更好的解决方案了吗?