36

I believe Google suggests developers to use AsyncTask. However, I would like to know how is it different from using 'new Thread' and then calling 'RunOnUiThread' in performance and memory efficiency.

Example for using RunOnUithread:

    // some code #1
    Thread t = new Thread("Thread1") {
        @Override
        public void run() {
            // some code #2
            runOnUiThread(new Runnable() {
                public void run() {
                    // some code #3 (that needs to be ran in UI thread)

                }
            });

        }
    };
    t.start();

vs.

AsyncTask:

onPreExecute() {
   // some code #1
}

doInBackground() {
   // some code #2
}

onPostExecute() {
   // some code #3
}

What are the advantages / disadvantages?

Edit:

I am not looking for answers like 'easier to see the code', 'convenient for developers' etc. I am actually looking for technical diffrences behind the scene.

For example, Paul Nikonowicz's answer below would have been the answer I wanted to see. (But AsyncTask behaves the same)

jclova
  • 5,466
  • 16
  • 52
  • 78

5 Answers5

53

When you use new Thread you're really creating a new thread every time you execute that. AsyncTask however, uses a static pool of max 128 threads and will reuse an old thread whenever it exists. So, running AsyncTask 10 times in serial will only create one thread that runs the task 10 times instead of 10 threads.

That's one of the differences among many.

JDJ
  • 4,298
  • 3
  • 25
  • 44
Randy Sugianto 'Yuku'
  • 71,383
  • 57
  • 178
  • 228
  • 4
    thank you. Something I wanted to hear. If you know some other differences, I would like to know. Also, how did you know AsyncTask has a static pool of max 128 threads? – jclova Feb 16 '12 at 15:55
  • 2
    Yeah.. how did you know AsyncTask has a static pool of 128 threads..? – songyy Oct 16 '12 at 18:44
  • 6
    @songyy https://github.com/android/platform_frameworks_base/blob/master/core/java/android/os/AsyncTask.java#L181 - 5 core threads that always run, upper limit of 128 threads. If more that 5 threads exist they will be killed if they idle for longer than a second. – zapl Dec 20 '12 at 17:24
13

It's a convenience, essentially. The AsyncTask framework deals with managing the Thread pool and provides a simple, understandable interface. It's well-known -- by those that know how to use AsyncTask -- that UI activity can go on in onPreExecute(), onPostExecute() and onProgressUpdate(), and that all of the "heavy lifting" is done in doInBackground() where you can't touch the UI.

It makes it easy for a developer to have a simple background task that can easily post updates to the UI thread and return results when done. It's not magic, it's just a convenience.

Brian Dupuis
  • 8,136
  • 3
  • 25
  • 29
5

According to this, AsyncTask is easier to use, but has some limitations like the following:

  • Core pool size and Work queue is fixed: 5 pools / 10 elements
    • it's hard coded and can't be changed
  • Thread priority is fixed to low
  • Exception handling is not as well supported as with Thread

Also there will be another difference that I haven't figured out. You can find and inspect full source code of AsyncTask since Android is opensource :-)

Have a good time with coding in Android!

JDJ
  • 4,298
  • 3
  • 25
  • 44
Joon Hong
  • 1,337
  • 15
  • 23
4

The main disadvantage is that using your own Thread will keep your activity alive when finish is called. Android will give your activity time for all of your threads to finish. This has the effect of creating an activity leak that will eventually cause your app to run very very slow until your app is force quit from either the user or the OS.

You can verify this by looking at your process in ADB. Even when the activity is finished you will still see it hanging there taking up resources.

So, if you use your own thread, make sure you manage it. Or, just use the android api's. the choice is yours.

Paul Nikonowicz
  • 3,883
  • 21
  • 39
  • 4
    An AsyncTask may also continue to execute after #onDestroy if you do not call AsyncTask#cancel(boolean) on it (which also assumes that the implementer has taken proper care to handle interrupts or check AsyncTask#isCancelled() in a timely fashion). – Jens Feb 15 '12 at 16:01
  • oh really? you should edit my answer to get the points :) That is good to know! Thank you. – Paul Nikonowicz Feb 15 '12 at 16:03
  • @Jens I thought AsyncTask is tied to an activity that it runs in, and it gets destroyed once the activity is destroyed too. – IgorGanapolsky Dec 13 '12 at 22:25
  • 3
    @IgorGanapolsky Nope, it isn't - but if you implement them poorly they can easily hold on to an Activity that has already been destroyed (for long running tasks this means you're leaking resources & other problems if you try to change views etc.) – Jens Dec 14 '12 at 08:04
  • @Jens is correct, refer to "http://blog.danlew.net/2014/06/21/the-hidden-pitfalls-of-asynctask/", althought Asynctask get affected when the screen rotated where the activity is destroyed and recreated, but on the "AsyncTasks and the Lifecycle" section, it talked about possible memory bogged. All along I thought of the opposite when screen rotated, thanks Jens. – TPG Jun 17 '15 at 07:53
2

These are HUGELY different.

  • First ALL user interaction is done on the main thread as well as all graphics work.
  • Second AsyncTask is designed for short spurts of dedicated activity, such as downloading a file or uploading some data.
  • Third because all UI and user interactions is done in the main thread, if you start pushing stuff to this thread, the device will appear to lag and be less responsive to the user's commands.

The only reason you want to run something in the UI thread is to interact with widgets. Other than that, if you want to do long processing, use an AsyncTask.

Edit:

You could download your data in a separate thread, and I have no issues with that. The problem comes when you want to update the UI. Alone, it is impossible to modify the UI from a child thread. Instead, you will have to create either a handler tied to the UI thread or create a new thread that is destined to run in the UI thread (as in your example). This is not only tedious, but a tragic waste of resources. The AsyncTask takes care of this simply and efficiently.

To address your last point, you are correct. The AsyncTask does have access to the main thread in pre/postExecute. However, the processing (the primary source of the UI lag) that the task is preforming is not. With the Task, the UI will only be impacted based on what you are drawing, as opposed to having to wait for the Task to finish its job and whatever drawing it wants to do.

JDJ
  • 4,298
  • 3
  • 25
  • 44
ahodder
  • 11,353
  • 14
  • 71
  • 114
  • 1
    I could be wrong but I have to disagree with you. - I agree with your first point. UI thread = main thread - It is also possible to implement downloading a file with 'new thread()' method. (Unless you tell me there's something more in AsyncTask) - AsyncTask's onPreExecute() & onPostExecute() also runs in UIThread(Main thread). So if you start pushing stuff to this thread, the device will also appear to lag and be less responsive to the users commands. – jclova Feb 16 '12 at 00:09
  • Re "if you want to do long processing, use an AsyncTask." Strictly speaking, not **long** processing, just **medium** processing (several seconds). See http://developer.android.com/reference/android/os/AsyncTask.html. – ToolmakerSteve Nov 07 '14 at 15:48
  • @jclova Re: "onPreExecute and onPostExecute also runs in UIThread .. the device will also appear to lag". What point are you trying to make? The entire purpose of AsyncTask is to easily combine UI-touching logic (in onPreExecute, onProgressUpdate, and onPostExecute) with longer-running logic that doesn't need to touch the UI (in doInBackground). Obviously if you put long running logic where it doesn't belong, that would cause problems - but to imply this is an inherent flaw in AsyncTask is simply wrong. – ToolmakerSteve Nov 07 '14 at 15:53
  • @jclova ... if you create a new thread, and also need to affect the UI, you would have to use a different mechanism to run the UI-touching logic on the UI thread. `getActivity().runOnUIThread`, or interaction with a Handler you had created via `Handler handler = new Handler(Looper.getMainLooper());`. In terms of UI responsiveness, the results would be identical, AFAIK. – ToolmakerSteve Nov 07 '14 at 16:00