编辑:
这不是关于精度问题,从下面的代码和日志中,你可以看到我要求睡眠1秒,但结果差不多200秒,有时它可能会跳到600秒,这不可能是精度问题..
之前我正在使用handlerthread,有时发布到处理程序的作业没有按时启动,为了获得更多细节我将其更改为基本Thread,并且事实证明Thread.sleep()是问题,但我和#39;我不知道如何解决这个问题,原因可能是什么?
hGpsThread = new Thread(mGpsWorker);
hGpsThread.start();
private final Runnable mGpsWorker = new Runnable() {
@Override
public void run() {
long lastGpsRequestTime = 0;
l.Write("GPS thread started.");
while (isRunning) {
l.Write("GPS thread loop start.");
try {
long currentTimeMillis = System.currentTimeMillis();
if (currentTimeMillis >= lastGpsRequestTime + gpsUpdateInterval) {
l.Write("Requesting location update");
gpslib.getLocation();
lastGpsRequestTime = currentTimeMillis;
}
l.Write("GPS thread before sleep");
Thread.sleep(1000);
l.Write("GPS thread after sleep");
} catch (InterruptedException e) {
}
l.Write("GPS thread loop end.");
}
l.Write("GPS thread ended.");
}
};
注意:getLocation()使用来自另一个线程的looper调用requestLocationUpdates,因此我理解,位置更新不应该影响这个线程。
getLocation()还会创建一个Timer并安排超时,这可能是问题吗?据我所知,这应该不是问题。
这是日志:(这只会偶尔发生,说机会接近0.5%)
Wed Jul 10 11:45:46 AEST 2013 GPS thread loop start.
Wed Jul 10 11:45:46 AEST 2013 GPS thread before sleep
Wed Jul 10 11:49:04 AEST 2013 GPS thread after sleep
Wed Jul 10 11:49:04 AEST 2013 GPS thread loop end.
由于
测试环境是:HTC Aria,Android 2.2 并且看起来像只有在使用电池运行时才会发生,但我的应用对充电状态的行为不同。
答案 0 :(得分:9)
只要屏幕开启,基本上Thread.sleep()
和Handlers
就可以正常工作(暗示Android不应处于深度睡眠状态/屏幕关闭状态)。
当屏幕关闭时,默认的Android行为是暂停Thread.sleep()和Handlers(),直到再次重新打开屏幕或某些应用程序抓住唤醒锁被唤醒。因此,如果屏幕全部打开,您的应用程序将完美运行,但是当它关闭时,它将表现不正常。
最好的解决方法是切换到AlarmManager
因为触发闹钟时,onRecieve()
默认会抓取唤醒锁,导致Android唤醒并执行。
答案 1 :(得分:0)
sleep()
documentation警告说这不准确:
无法保证精度 - 线程可能会或多或少地睡眠 比要求。
有许多与sleep()
精确度无关的问题,如this one,this one等等。谷歌为“java线程睡眠精度”或“android线程睡眠精度”。
答案 2 :(得分:0)
我也说出这个问题,而不是它不够精确,但是不是10秒,而是等待了30分钟 - 对于一个运行数周而且必须定期执行请求的应用程序,这不是解决方案。因此,我制作了BetterSleeper: - )
import java.sql.Timestamp;
public class BetterSleeper {
public static void sleepSeconds(int seconds_to_wait) {
System.out.println("START WAIT FOR "+seconds_to_wait+" SECONDS");
BetterSleeper.sleepMillis(seconds_to_wait*1000);
System.out.println("END WAIT");
}
public static void sleepMillis(int milliseconds_to_wait) {
System.out.println("START WAIT FOR "+milliseconds_to_wait+" MILLISECONDS");
Timestamp timestamp = new Timestamp(System.currentTimeMillis());
long start_milliseconds = timestamp.getTime();
long end_milliseconds = start_milliseconds + milliseconds_to_wait;
while (true) {
Timestamp endtime = new Timestamp(System.currentTimeMillis());
if ((endtime.getTime()) >= end_milliseconds) {
break;
}
}
System.out.println("END WAIT");
}
}
如果你考虑到这个片段中的处理时间实际上几乎没有任何影响,这实际上证明更加准确,因为它在开始时被记住并且它应该在开始时停止。
另一个优点是你不具备调度睡眠线程的所有缺点,例如Thread.sleep,如果终止主线程,后台线程将被放弃。
注意我与Android开发无关 - 我的问题发生在运行Windows 10的Windows PC上。