Executing Multiple Asynctask's Parallely

Executing Multiple AsyncTask's Parallely

This is how I do that:

if( Build.VERSION.SDK_INT >= Build.VERSION_CODES.HONEYCOMB ) {
new MyAsyncTask().executeOnExecutor(AsyncTask.THREAD_POOL_EXECUTOR);
} else {
new MyAsyncTask().execute();
}

where MyAsyncTask is regular AsyncTask subclass. Or you can wrap this all in helper class:

class TaskHelper {

public static <P, T extends AsyncTask<P, ?, ?>> void execute(T task) {
execute(task, (P[]) null);
}

@SuppressLint("NewApi")
public static <P, T extends AsyncTask<P, ?, ?>> void execute(T task, P... params) {
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.HONEYCOMB) {
task.executeOnExecutor(AsyncTask.THREAD_POOL_EXECUTOR, params);
} else {
task.execute(params);
}
}
}

and then just do:

TaskHelper.execute( new MyTask() );

or

TaskHelper.execute( new MyTask(), args );

or

TaskHelper.execute( new MyTask(constructorParams), args );

Running multiple AsyncTasks at the same time -- not possible?

AsyncTask uses a thread pool pattern for running the stuff from doInBackground(). The issue is initially (in early Android OS versions) the pool size was just 1, meaning no parallel computations for a bunch of AsyncTasks. But later they fixed that and now the size is 5, so at most 5 AsyncTasks can run simultaneously. Unfortunately I don't remember in what version exactly they changed that.

UPDATE:

Here is what current (2012-01-27) API says on this:

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. After HONEYCOMB, it is planned to change this back to 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.

DONUT is Android 1.6, HONEYCOMB is Android 3.0.

UPDATE: 2

See the comment by kabuko from Mar 7 2012 at 1:27.

It turns out that for APIs where "a pool of threads allowing multiple tasks to operate in parallel" is used (starting from 1.6 and ending on 3.0) the number of simultaneously running AsyncTasks depends on how many tasks have been passed for execution already, but have not finished their doInBackground() yet.

This is tested/confirmed by me on 2.2. Suppose you have a custom AsyncTask that just sleeps a second in doInBackground(). AsyncTasks use a fixed size queue internally for storing delayed tasks. Queue size is 10 by default. If you start 15 your custom tasks in a row, then first 5 will enter their doInBackground(), but the rest will wait in a queue for a free worker thread. As soon as any of the first 5 finishes, and thus releases a worker thread, a task from the queue will start execution. So in this case at most 5 tasks will run simultaneously. However if you start 16 your custom tasks in a row, then first 5 will enter their doInBackground(), the rest 10 will get into the queue, but for the 16th a new worker thread will be created so it'll start execution immediately. So in this case at most 6 tasks will run simultaneously.

There is a limit of how many tasks can be run simultaneously. Since AsyncTask uses a thread pool executor with limited max number of worker threads (128) and the delayed tasks queue has fixed size 10, if you try to execute more than 138 your custom tasks the app will crash with java.util.concurrent.RejectedExecutionException.

Starting from 3.0 the API allows to use your custom thread pool executor via AsyncTask.executeOnExecutor(Executor exec, Params... params) method. This allows, for instance, to configure the size of the delayed tasks queue if default 10 is not what you need.

As @Knossos mentions, there is an option to use AsyncTaskCompat.executeParallel(task, params); from support v.4 library to run tasks in parallel without bothering with API level. This method became deprecated in API level 26.0.0.

UPDATE: 3

Here is a simple test app to play with number of tasks, serial vs. parallel execution: https://github.com/vitkhudenko/test_asynctask

UPDATE: 4 (thanks @penkzhou for pointing this out)

Starting from Android 4.4 AsyncTask behaves differently from what was described in UPDATE: 2 section. There is a fix to prevent AsyncTask from creating too many threads.

Before Android 4.4 (API 19) AsyncTask had the following fields:

private static final int CORE_POOL_SIZE = 5;
private static final int MAXIMUM_POOL_SIZE = 128;
private static final BlockingQueue<Runnable> sPoolWorkQueue =
new LinkedBlockingQueue<Runnable>(10);

In Android 4.4 (API 19) the above fields are changed to this:

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 BlockingQueue<Runnable> sPoolWorkQueue =
new LinkedBlockingQueue<Runnable>(128);

This change increases the size of the queue to 128 items and reduces the maximum number of threads to the number of CPU cores * 2 + 1. Apps can still submit the same number of tasks.

Android Execute Multiple AsyncTask Parallely

Quoting AsyncTask class from Android developers

AsyncTask is designed to be a helper class around Thread and Handler
and does not constitute a generic threading framework. AsyncTasks
should ideally be used for short operations (a few seconds at the
most.) If you need to keep threads running for long periods of time,
it is highly recommended you use the various APIs provided by the
java.util.concurrent package such as Executor, ThreadPoolExecutor and
FutureTask.

Internally the AsyncTask is implemented via an Executor and the default one is SerialExecutor.

The the point of having a limit == number of CPU cores is that if the limit was bigger, than there'll be a constant race between the started threads. You know that end of the day you can have just threads working at the same moment. In many cases this race between threads is not a problem, but in some it is. I guess Google just decided the pros are less than the cons and that's why they returned to SerialExecutor again. Again, quoting from AsyncTask class description:

Starting with HONEYCOMB, tasks are executed on a single thread to avoid common application errors caused by parallel execution.

These problems are mostly InterruptedException and IllegalStateException.

Lastly, if you really know what you're doing and have a solid reason to override Google's default behaviour you can do so by using AsyncTask.executeOnExecutor(Executor, Object[]), passing in a THREAD_POOL_EXECUTOR.

Is it possible to run multiple AsyncTask in same time?

use executor as follows

if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.HONEYCOMB) {
new Save_data().executeOnExecutor(AsyncTask.THREAD_POOL_EXECUTOR, location);
} else {
new Save_data().execute(location);
}

See this

Multiple AsyncTasks with sequential execution

From AsyncTask docs:

Starting with HONEYCOMB, tasks are executed on a single thread to avoid common application errors caused by parallel execution.

so if you are not >= HONEYCOMB, then maybe switch to use ExecutorService:

ExecutorService executor = Executors.newSingleThreadExecutor();

How to execute multi AsyncTask Serial or Parallel?

You can execute multiple AsyncTask simultaniously there is no issue,

because every AsyncTask will run in a Separate Worker Thread so it don't effect on the Main Thread.

I/Choreographer﹕ Skipped 39 frames! The application may be doing too
much work on its main thread.

Actually you are running on emulator so compare to real device it is too slow, so you will see the above messages in common.If you run on a real device you don't see that kind of messages.

Hope this will helps you.



Related Topics



Leave a reply



Submit