Android Asynctask Threads Limits

Android AsyncTask threads limits?

All AsyncTasks are controlled internally by a shared (static) ThreadPoolExecutor and a LinkedBlockingQueue. When you call execute on an AsyncTask, the ThreadPoolExecutor will execute it when it is ready some time in the future.

The 'when am I ready?' behavior of a ThreadPoolExecutor is controlled by two parameters, the core pool size and the maximum pool size. If there are less than core pool size threads currently active and a new job comes in, the executor will create a new thread and execute it immediately. If there are at least core pool size threads running, it will try to queue the job and wait until there is an idle thread available (i.e. until another job is completed). If it is not possible to queue the job (the queue can have a max capacity), it will create a new thread (up-to maximum pool size threads) for the jobs to run in. Non-core idle threads can eventually be decommissioned according to a keep-alive timeout parameter.

Before Android 1.6, the core pool size was 1 and the maximum pool size was 10. Since Android 1.6, the core pool size is 5, and the maximum pool size is 128. The size of the queue is 10 in both cases. The keep-alive timeout was 10 seconds before 2.3, and 1 second since then.

With all of this in mind, it now becomes clear why the AsyncTask will only appear to execute 5/6 of your tasks. The 6th task is being queued up until one of the other tasks complete. This is a very good reason why you should not use AsyncTasks for long-running operations - it will prevent other AsyncTasks from ever running.

For completeness, if you repeated your exercise with more than 6 tasks (e.g. 30), you will see that more than 6 will enter doInBackground as the queue will become full and the executor is pushed to create more worker threads. If you kept with the long-running task, you should see that 20/30 become active, with 10 still in the queue.

Is there a limit of AsyncTasks to be executed at the same time?

Yes, there's a limit. AsyncTask is backed by a ThreadPoolExecutor with a core pool size of 5, but a maximum pool size of 128 (from 1.6 - 4.0.3), so really I would think you should see all 10 of yours run at once. You can't change it though. If you really want to do something different (and I wouldn't recommend it unless you have a very specific reason), you'll have to do something custom with a larger pool size or just spin up a bunch of threads manually.

Update:

Here's what the docs say:

If there are more than corePoolSize but less than maximumPoolSize threads running, a new thread will be created only if the queue is full.

So that's why. Your queue isn't full, so it just keeps it at the core pool size.

How to limit the number of threads launched using ASyncTask?

Right now, unless you are willing to limit yourself to API Level 11 (Android 3.0) and higher, you cannot limit the number of threads used by AsyncTask. IIRC, it will use up to 20 threads maximum.

If you want fewer than that, you will need to create your own thread pool mechanism and use that instead of AsyncTask. Or, clone the code from AsyncTask into your own project and modify the characteristics of its own thread pool.

How many async task can be used in a class android?

The question itself does not make any sense. You can use as many AsyncTask in a class as you want, if there were a restriction on that it would be ridiculous. I assume he meant how many AsyncTask can be executed at the same time and how they are executed and the answer to that would be: It depends.

AsyncTasks can be executed either in series or in parallel. The default behaviour depends on the API level of the device. The documentation of execute() of AsyncTask says:

Note: this function schedules the task on a queue for a single
background thread or pool of threads depending on the platform
version. When first introduced, AsyncTasks were executed serially on a
single background thread. Starting with DONUT, this was changed to a
pool of threads allowing multiple tasks to operate in parallel.
Starting HONEYCOMB, tasks are back to being executed on a single
thread to avoid common application errors caused by parallel
execution. If you truly want parallel execution, you can use the
executeOnExecutor(Executor, Params...) version of this method with
THREAD_POOL_EXECUTOR; however, see commentary there for warnings on
its use.

Having said that you can choose whether you want to execute them in parallel or in series like this:

// Executes the task in parallel to other tasks
asyncTask.executeOnExecutor(AsyncTask.THREAD_POOL_EXECUTOR);

// Adds the task to a queue and executes one at a time.
asyncTask.executeOnExecutor(AsyncTask.SERIAL_EXECUTOR);

However even if you run the tasks in parallel there is a limit to how many can run at the same time. To find out where that limit is you have to look into the source code of AsyncTask.

Up until Android 4.3 (Jelly Bean) the limits were hardcoded to those values:

private static final int CORE_POOL_SIZE = 5;
private static final int MAXIMUM_POOL_SIZE = 128;
private static final int KEEP_ALIVE = 1;

But with Android 4.4 that was changed and the limits are calculated depending on the used processor in the device:

private static final int CPU_COUNT = Runtime.getRuntime().availableProcessors();
private static final int CORE_POOL_SIZE = CPU_COUNT + 1;
private static final int MAXIMUM_POOL_SIZE = CPU_COUNT * 2 + 1;
private static final int KEEP_ALIVE = 1;

The implementation of the ThreadPoolExecutor remained the same in both cases:

public static final Executor THREAD_POOL_EXECUTOR
= new ThreadPoolExecutor(CORE_POOL_SIZE, MAXIMUM_POOL_SIZE, KEEP_ALIVE,
TimeUnit.SECONDS, sPoolWorkQueue, sThreadFactory);

So that should pretty much answer your question. But if you really want to find out how the AsyncTask works then you should study the source code yourself! This link leads to the AsyncTask implementation on Android 4.4.



Related Topics



Leave a reply



Submit