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
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.
aSync Task can't be executed twice
As the exception itself explains, you cannot execute an AsyncTask
more than once, unless you create a new
instance of it and call .execute
.
For example:
async = new AsyncTask();
async.execute();
*in order to execute more than once, you need to re-create the instance (using new
) the number of times you want to execute it.
Execute AsyncTask several times
AsyncTask
instances can only be used one time.
Instead, just call your task like new MyAsyncTask().execute("");
From the AsyncTask API docs:
Threading rules
There are a few threading rules that must be followed for this class to work properly:
- The task instance must be created on the UI thread.
- execute(Params...) must be invoked on the UI thread.
- Do not call onPreExecute(), onPostExecute(Result), doInBackground(Params...), onProgressUpdate(Progress...) manually.
- The task can be executed only once (an exception will be thrown if a second execution is attempted.)
Running same Asynctask multiple times sequentially
You could use a field variable in the outer class:
private int count;
private void attemptConnect(){
count = 0;
new MyTask().execute("");
}
class MyTask extends AsyncTask<String, String, String> {
@Override
protected String doInBackground(String... params) {
return null;
}
@Override
protected void onPostExecute(String s) {
count++;
if(count < 5){
new MyTask().execute("");
}
}
}
Or pass in a count to the AsyncTask constructor:
private void attemptConnect(){
new MyTask(0).execute("");
}
class MyTask extends AsyncTask<String, String, String> {
private int count;
public MyTask(int count){
this.count = count;
}
@Override
protected String doInBackground(String... params) {
return null;
}
@Override
protected void onPostExecute(String s) {
if(count < 4){
new MyTask(++count).execute("");
}
}
}
AsyncTask and error when executed twice
No. You cannot execute the same async task twice. You are able to do it again after 30 secs because the async task completes processing and returns the result from doInBackground(). Hence you need to create an object every time or use a progress dialog to block the user from clicking on the button again. Show the progress dialog in onPreExecute() and dismiss in onPostExecute().
How to make more than one Android AsyncTask run at the same time?
Use executeOnExecutor(AsyncTask.THREAD_POOL_EXECUTOR)
instead of execute()
. Quoting the AsyncTask
documentation:
If you truly want parallel execution, you can invoke executeOnExecutor(java.util.concurrent.Executor, Object[]) with THREAD_POOL_EXECUTOR.
Related Topics
How to Fix Android Studio Getting Stuck Executing Gradle Tasks
Android: Why Does Long Click Also Trigger a Normal Click
How to Embed Vlc Media Player to My Android App
Detecting Outgoing Call and Call Hangup Event in Android
Android Get Application's 'Home' Data Directory
Android: Is There Any Free PDF Library for Android
How to Know If Android Talkback Is Active
How to Change The Overscroll Color in Android 2.3.1
How to Set Status Bar Background as Gradient Color or a Drawable in Android
Linearlayout Height in Oncreate Is 0
How to Hide The System/Navigation Bar in Android Ics
How to Access an Existing Sqlite Database in Android
End Incoming Call Programmatically
Android Tablayout Android Design