agou
agou

Reputation: 738

Android Thread.sleep sometimes waits far too long

Edit:

This is not talking about precision issues, from the code and log below, you can see that I requested to sleep for 1 second, but the result was almost 200 seconds, sometimes it could jump to 600 seconds, this cannot be a precision issue..


I was using handlerthread before and sometimes the job posted to handler just does not start on time, to get more details I changed it to the basic Thread, and it turns out the Thread.sleep() is the issue, but I'm not sure how to fix this, what could be the possible reasons?

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.");
    }
};

NOTE: getLocation() calls requestLocationUpdates using a looper from another thread, so location updating should not affect this thread, as I understand.

getLocation() also creates a Timer and schedules a timeout, could that be the issue? as I understand it should not be an issue.

This is the log: (this only happens occasionally, say the chance is close to 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.

Thanks

The testing environment is: HTC Aria, Android 2.2 And looks like it only happens when running on battery, but my app doesn't act differently on charging status.

Upvotes: 3

Views: 3885

Answers (3)

Florian Müller
Florian Müller

Reputation: 7785

I also hat that problem, not that it was not precise enough, but instead of 10 seconds, the Thread waited for 30 minutes - for an application, which runs over weeks and which has to perform requests periodically, this is no solution. Therefore, I made the 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");
    }
}

This actually proves to be much more accurate, if you take into consideration that processing time in this snippet actually takes almost no effect, because it is remembered when it started and when it should stop right at the beginning.

Another advantage is you don't have all the disadvantages of a dispatched sleeping thread like with Thread.sleep, where background threads are being abandonned if you terminate the main thread.


NOTE I had nothing to do with Android development - my problem occurred on a Windows PC running Windows 10.

Upvotes: -1

Royston Pinto
Royston Pinto

Reputation: 6731

Basically Thread.sleep() and Handlers work fine as long as the screen is on (implies Android should not be in a deep sleep state/screen off state).

When the Screen is turned off, default Android behavior is to suspend Thread.sleep() and Handlers() until the screen is turned back on again or if it is woken up by some application grabbing a wakelock. Hence your application will work perfectly if the screen is on throughout, but when it is turned off, it will behave erratically.

The best work around is to switch to AlarmManager because when the Alarm is triggered, onRecieve() always grabs a wakelock by default causing Android to wake up and execute.

Upvotes: 9

Christian Garbin
Christian Garbin

Reputation: 2532

The sleep() documentation warns that it's not precise:

The precision is not guaranteed - the Thread may sleep more or less than requested.

There is a number of questions related to the lack of precision of sleep(), like this one, this one and a few more. Google for "java thread sleep precision" or "android thread sleep precision".

Upvotes: 0

Related Questions