Rakesh
Rakesh

Reputation: 1133

Are threads reliable enough to calculate seconds?

I am making an Android App that at some activity shows a timer with hours minutes and seconds. As seconds value will update every second, I was thinking to make a thread with 1000 ms sleep, after each cycle it will add 1 to seconds and update the text view. Accordingly it will calculate minutes and hours and update the respective text views.

But I have one doubt in mind, are threads reliable enough to accomplish such a task or should I use inbuilt library function to get seconds after every cycle ? I am a little concerned about getting my timer getting out of sync if I rely completely on thread to calculate time.

Upvotes: 6

Views: 380

Answers (9)

Saj
Saj

Reputation: 18712

Use Handler. Here's a very good detailed post on that.

long startTime = 0;

Handler timerHandler = new Handler();

Runnable timerRunnable = new Runnable() {
    @Override
    public void run() {
        long millis = System.currentTimeMillis() - startTime;
        int seconds = (int) Math.round(diff / ((double)1000));
        int minutes = (int) Math.round(seconds / ((double)60));
        seconds = seconds % 60;

        // Use the seconds

        timerHandler.postDelayed(this, 500);
    }
};

Start timer-

startTime = System.currentTimeMillis();
timerHandler.postDelayed(timerRunnable, 0);

Stop timer-

timerHandler.removeCallbacks(timerRunnable);

On pause-

timerHandler.removeCallbacks(timerRunnable);

Upvotes: 6

ddmps
ddmps

Reputation: 4380

As others have pointed out, sleep(millis) only guarantees to sleep for at least the amount of milliseconds - which means if you use 1000 instead of an offset it will be lagging behind.

Use with offset:

long last = System.currentTimeMillis();
while (true) {
   long current = System.currentTimeMillis();
   Thread.sleep(last-current);
   last = current;
   incrementSeconds();
}   

Upvotes: 1

kathir
kathir

Reputation: 489

Its not possible with simple thread with sleep in android. Just use runnable thread.

Start this when u need to update your textview according to seconds . In this i tried with minutes, seconds and millise3conds .

Just check it out.

Create a textview , nd set text with the below runnable.

 private Runnable updateTimerThread = new Runnable() {

        public void run() {

            timeInMilliseconds = SystemClock.uptimeMillis() - startTime;

            updatedTime = timeSwapBuff + timeInMilliseconds;

            int secs = (int) (updatedTime / 1000);
            int mins = secs / 60;
            secs = secs % 60;
            int milliseconds = (int) (updatedTime % 1000);
            t1.setText("" + mins + ":"
                    + String.format("%02d", secs) + ":"
                    + String.format("%03d", milliseconds));
            customHandler.postDelayed(this, 0);
        }

    };

Upvotes: 1

nogard
nogard

Reputation: 9716

Sleep with 1000 ms delay is bad option, since there is always a jitter and also some CPU time is spent on execution of your routine.

I would propose to profit from ScheduledExecutorService.scheduleAtFixedRate method, that will call your implementation at fixed rate.

Upvotes: 3

jbx
jbx

Reputation: 22158

While if you say sleep for 1 second the thread will sleep for 1 second, the actual time at which your instruction takes place when the thread wakes up depends on other factors such as thread scheduling of the OS and the CPU. Its unlikely it will have a huge impact, but why don't you simply keep track of the actual timestamps so that you know exactly how much time has elapsed, and correct accordingly if there is any difference?

You can use something simple like System.currentTimeMillis()

Upvotes: 1

PeterMmm
PeterMmm

Reputation: 24630

But I have one doubt in mind, are threads reliable enough to accomplish such a task

No, they aren't.

You can use a thread to update the clock display but you should read System.currentTimeMillis() (or similiar) again.

Upvotes: 1

Lie Ryan
Lie Ryan

Reputation: 64915

Sleep is not good enough.

Sleep will pause the thread for a minimum of the specified period of time, but the actual sleep period may be longer than the specified time.

Upvotes: 8

Tanmay Patil
Tanmay Patil

Reputation: 7057

Thread sleep should never be relied upon. It does not guaranty the exact time difference.

I'd suggest you to use a timer task. It's easy to use and considerably reliable.

Good luck.

Upvotes: 2

Keppil
Keppil

Reputation: 46229

With the logic you have described you will indeed get some drifting, i.e. the small error you may get every cycle will add up to a significant amount. It is easily remedied though.

Just keep a variable holding the time of the last trigger. When the sleep is done, add 1000 to the last trigger time, calculate the remainder until that time, and sleep for that long instead. This way you may get the occasional late trigger, but it will quickly be remedied.

Upvotes: 2

Related Questions