在android中,在精确的n毫秒后重复一个任务

在android中,在精确的n毫秒后重复一个任务,android,timer,Android,Timer,我的要求是每n毫秒对安卓传感器数据进行采样 尝试使用计时器、报警管理器和处理程序。任务正在重复,但持续时间不是精确的n毫秒 代码:: 处理: Handler sensorHandler = new Handler(); private Runnable sensorRunnable = new Runnable() { @Override public void run() { sendAllSensorData();

我的要求是每n毫秒对安卓传感器数据进行采样

尝试使用
计时器
报警管理器
处理程序
。任务正在重复,但持续时间不是精确的n毫秒

代码::

处理:

Handler sensorHandler = new Handler();
    private Runnable sensorRunnable = new Runnable() {
        @Override
        public void run() {
            sendAllSensorData();
            sensorHandler.postDelayed(sensorRunnable, 50);
        }
    };

    private void postSensorMsgHandler() {
        sensorHandler.postDelayed(sensorRunnable, 50);
    }
计时器:: 私有void initTimer(){

定时器=新定时器()

}

日志::

06-22 15:34:53.201 D/Telemetric(27434): Telemetric Gyroscope Y mean = -0.000533 sd = 0.000958 variance = 0.000001

06-22 15:34:53.212 D/Telemetric(27434): Telemetric Gyroscope Y mean = 0.001057 sd = 0.000000 variance = 0.000000

06-22 15:34:53.253 D/Telemetric(27434): Telemetric Gyroscope Y mean = 0.000524 sd = 0.000754 variance = 0.000001

06-22 15:34:53.264 D/Telemetric(27434): Telemetric Gyroscope Y mean = -0.000009 sd = 0.001066 variance = 0.000001

06-22 15:34:53.306 D/Telemetric(27434): Telemetric Gyroscope Y mean = 0.000524 sd = 0.001376 variance = 0.000002

06-22 15:34:53.317 D/Telemetric(27434): Telemetric Gyroscope Y mean = 0.000844 sd = 0.001390 variance = 0.000002

06-22 15:34:53.361 D/Telemetric(27434): Telemetric Gyroscope Y mean = 0.000702 sd = 0.001291 variance = 0.000002

06-22 15:34:53.370 D/Telemetric(27434): Telemetric Gyroscope Y mean = 0.000600 sd = 0.001209 variance = 0.000001

06-22 15:34:53.414 D/Telemetric(27434): Telemetric Gyroscope Y mean = 0.000391 sd = 0.001266 variance = 0.000002

06-22 15:34:53.423 D/Telemetric(27434): Telemetric Gyroscope Y mean = 0.000465 sd = 0.001205 variance = 0.000001
试试这个

//Create Timer Object 
Timer t = new Timer();
//Set your schedule time
t.scheduleAtFixedRate(new TimerTask() {

    @Override
    public void run() {
        //Called each time when 1000 milliseconds (1 second)
    }

},
//Set start timing (milliseconds)
0,
//Set interval time(milliseconds)
1000);
Android不是一个“实时操作系统”,要获得你想要的高精度,你可能需要另一个硬件,例如一些嵌入式的,比如Raspberry。。。还有另一种操作系统,例如一些“实时Linux”
为什么不使用Android框架的常规传感器轮询机制呢


您可以使用这样的方法:在线程
run()
方法的循环中进行工作,并计算它的持续时间(比如
工作持续时间
),而不是睡眠时间
50000000-工作持续时间
(其中50000000是50毫秒,单位为纳秒),然后继续循环:

...
new Thread(new Runnable() {
    @Override
    public void run() {
        try {
            while (true) {
                long startTime = System.nanoTime();

                // do your work here

                long workEndTime = System.nanoTime();
                long workDuration = workEndTime - startTime;
                long timeToSleep = 50000000 - workDuration;
                long timeToSleepMillis = timeToSleep / 1000000;
                int timeToSleepNanos = (int) (timeToSleep % 1000000);
                Thread.sleep(timeToSleepMillis, timeToSleepNanos);
            }
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
    }
}).start();
...

当然,任务重复的持续时间不是精确的n毫秒,而是非常接近n(取决于当前设备)。此外,您还可以稍微调整
timeToSleep
值,以获得更精确的睡眠时间。

如果您希望在某个确切时间运行一些
Runnable
,请使用
Handler\posttime
methodHandler sensorHandler=new Handler();private Runnable sensorRunnable=new Runnable(){@Override public void run(){Logger.d(“处理程序计时器::”+System.currentTimeMillis());sendAllSensorData();sensorHandler.posttime(sensorRunnable,SystemClock.uptimeMillis()+50);};private void postSensorMsgHandler(){sensorHandler.posttime(sensorRunnable,SystemClock.uptimeMillis()+50);}这是我的posttime代码。同一结果处理程序计时器::1498126539758处理程序计时器::1498126539782您要传递给
posttime
long uptimeMillis
值是多少?自系统启动以来,uptimeMillis以毫秒计。我的意思是您传递的确切值是多少,以及运行
Runnable
时,这两个时间戳的区别是什么?感谢Manoj的回答,我的用例旨在实现毫秒级的粒度。如果我用1秒,它就可以正常工作。知道吗?好的意思是它在几毫秒内不工作?请尝试此代码并放置毫秒。我用问题粘贴的代码具有计时器任务,其中TelemetricConstant.delay为0,TelemetricConstant.SAMPLE_周期为50。registerListener中的samplingPeriodUs参数不保证精确时间。它只是根据文档对系统的提示。我试过这个。同样的结果。samplingPeriodUs int:两个连续事件之间所需的延迟,以微秒为单位。这只是对系统的一个提示。接收事件的速度可能快于或慢于指定的速率。通常情况下,事件接收速度很快。您不能期望任何框架计时器的粒度小于16ms,实际上,您甚至不能期望这些计时器将为相同的参数保持相同的间隔(从长远来看,它们可能会在统计上与参数保持接近)。如果您真的需要精确的计时,那么就使用本机和平台硬件计时器。已经有人说过,Android不是一个实时系统,它试图通过分批处理多个应用程序/线程要完成的工作来优化性能和功耗,而不需要过多地切换硬件的功率级别。
...
new Thread(new Runnable() {
    @Override
    public void run() {
        try {
            while (true) {
                long startTime = System.nanoTime();

                // do your work here

                long workEndTime = System.nanoTime();
                long workDuration = workEndTime - startTime;
                long timeToSleep = 50000000 - workDuration;
                long timeToSleepMillis = timeToSleep / 1000000;
                int timeToSleepNanos = (int) (timeToSleep % 1000000);
                Thread.sleep(timeToSleepMillis, timeToSleepNanos);
            }
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
    }
}).start();
...