如何减少Android中的Thread.sleep()延迟

我在
Android应用程序的(非UI)线程中循环生成计时事件,我需要这些事件以精确的时间间隔发生,(这里的精确意味着不会超过/ – 5毫秒).用户可以感知到/ -10毫秒(当然/ – 20毫秒)的任何​​错误.在这个循环的顶部,我做了一些其他计算需要花费不同的时间,但是在循环的底部,我需要在预先计算的时间发生事件.

我的非UI线程的一次尝试的高度简化版本(无异常处理)如下:

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)同样是十分之一毫秒.

我绝对肯定calcutionsTakingVaryingAmountOfTime()总是少于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)调用时,调用this.wait(eventWait / 10L)(完全不恰当的使用wait(),我知道)
>我在进入循环之前操纵了线程优先级,调用Process.setThreadPriority(Process.THREAD_PRIORITY_URGENT_AUDIO)就像在整个android库中完成一样

但是这些延迟并没有任何改善.

一种方法可以稳定事件,并将延迟减少到不到2或3毫秒,并且很少打嗝是用轮询循环替换Thread.sleep()调用:

while ((System.nanoTime() / 100000L) < eventTime)
    ;

一方面,我感到尴尬的是像醉酒的水手一样花机器自行车.另一方面,我开始认为没有更好的方法,我应该在轮询循环中烧掉机器周期以减少延迟,并符合我的规范.当然,当我的应用程序转到后台时,我会暂停我的线程,因此这个轮询循环可以工作.但多么浪费.

任何想法将不胜感激.

最佳答案 我正在使用Handler的延迟消息用于类似目的.它可能有点矫枉过正.在你的情况下,我会看看Timer类.

mTimer = new Timer();
mTimer.scheduleAtFixedRate(new TimerTask() {
    @Override
    public void run() {
        Log.v("TEST", " tick");
    }
}, 0, 250);

这使我在模拟器上的延迟为-2毫秒.

点赞