Timertask VS Thread.Sleep VS Handler Postdelayed - Most Accurate to Call Function Every N Milliseconds

TimerTask vs Thread.sleep vs Handler postDelayed - most accurate to call function every N milliseconds?

There are some disadvantages of using Timer

  • It creates only single thread to execute the tasks and if a task
    takes too long to run, other tasks suffer.
  • It does not handle
    exceptions thrown by tasks and thread just terminates, which affects
    other scheduled tasks and they are never run

ScheduledThreadPoolExecutor deals properly with all these issues and it does not make sense to use Timer.. There are two methods which could be of use in your case.. scheduleAtFixedRate(...) and scheduleWithFixedDelay(..)

class MyTask implements Runnable {

@Override
public void run() {
System.out.println("Hello world");
}
}

ScheduledThreadPoolExecutor exec = new ScheduledThreadPoolExecutor(1);
long period = 100; // the period between successive executions
exec.scheduleAtFixedRate(new MyTask(), 0, period, TimeUnit.MICROSECONDS);
long delay = 100; //the delay between the termination of one execution and the commencement of the next
exec.scheduleWithFixedDelay(new MyTask(), 0, delay, TimeUnit.MICROSECONDS);

PostDelayed or Thread with thread.sleep()

I think you're mixing up some concepts. Handler's postDelayed() indeed will run a Runnable after some time lapse, but only once.

For what you want to do you've several choices:

  • Sleeping the Thread is one of them. A disatvantage of this is that the Thread might cause an exception and this way your execution could become unstable. Also, you'll have just one Thread and you won't free it up even if it's sleeping, so you're using resources that you might not need at a time.
  • Another approach is using an AsyncTask. This is recommended, however, for short tasks. If you plan running this task for a longer period of time, AsyncTask is probably not a good choice.
  • You can run a background Service with a Handler to update the UI. Depends on what you're trying to achieve.
  • You'll probably want to have a look at ScheduledExecutorService. It has a method called scheduleAtFixedRate() which will do exactly that, execute a Runnable each X time specified by one of the parameters. More info here.

Repeat method in short time interval

Context

Take into account the fact the Android uses it's own implementation of java.

There is no Java Virtual Machine in the Android platform. Java
bytecode is not executed. Instead Java classes are compiled into a
proprietary bytecode format and run on Dalvik, a specialized virtual
machine (VM) designed specifically for Android. Unlike Java VMs, which
are stack machines, the Dalvik VM is a register-based architecture.

Comparison of Java and Android API

So what holds true for the java virtual machine may not necessarily reflect on Android's implementation.

As a rule of thumbs it's better to use whatever the Android API makes available.

Solution

I recommend using the Handler.
Especially if you want to update views.

Even the official Android tutorials recommends :

To move data from a background thread to the UI thread, use a Handler
that's running on the UI thread.

From the start Timer gets excluded.

There are some disadvantages of using Timer It creates only single
thread to execute the tasks and if a task takes too long to run, other
tasks suffer. It does not handle exceptions thrown by tasks and thread
just terminates, which affects other scheduled tasks and they are
never run

From this answer.

And from the Android docs:

A ThreadPoolExecutor (i.e. ScheduledThreadPoolExecutor) is preferable to Timer when multiple worker threads are needed, or when
the additional flexibility or capabilities of ThreadPoolExecutor
(which this class extends) are required.

When using the Handler i recommend reading through this tutorial if you want to avoid memory leaks.

If it wasn't the case of an UI update a ThreadPoolExecutor would have been better because they provide improved performance when executing large numbers of asynchronous tasks, due to reduced per-task invocation overhead.

Handler().postDelayed is now deprecated. What function to call instead?

You need to use the constructor with an explicit looper, for the Main thread Looper use Looper.getMainLooper()

Handler(Looper.getMainLooper()).postDelayed({
notifyDataSetChanged()
}, 100)

Wait for 5 seconds

just add one-liner with lambda

(new Handler()).postDelayed(this::yourMethod, 5000);

edit for clarification: yourMethod refers to the method which you want to execute after 5000 milliseconds.

Android TimerTask not finish after app is closing

Assuming you want to stop it when the Activity is destroyed :

@Override
protected void onDestroy()
{
super.onDestroy();
yourTimer.cancel();
}

Or if you want to stop it when your activity is hidden :

@Override
protected void onStop()
{
super.onStop();
yourTimer.cancel();
}

According to the activity workflow, choose the best method where your timer has to be cancelled :

Sample Image

Where do I create and use ScheduledThreadPoolExecutor, TimerTask, or Handler?

I prefer to use ScheduledThreadPoolExecutor. Generally, if I understand your requirements correctly, all these can be implemented in your activity, TimerTask and Handler are not needed, see sample code below:

public class MyActivity extends Activity {
private ScheduledExecutorService scheduleTaskExecutor;

public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
scheduleTaskExecutor= Executors.newScheduledThreadPool(5);

// This schedule a task to run every 10 minutes:
scheduleTaskExecutor.scheduleAtFixedRate(new Runnable() {
public void run() {
// Parsing RSS feed:
myFeedParser.doSomething();

// If you need update UI, simply do this:
runOnUiThread(new Runnable() {
public void run() {
// update your UI component here.
myTextView.setText("refreshed");
}
});
}
}, 0, 10, TimeUnit.MINUTES);
} // end of onCreate()
}

Remember to finish/close your runnable task properly in Activity.onDestroy(), hope that help.



Related Topics



Leave a reply



Submit