How to limit the threads in the thread pool (Android) - android

When executing AysncTask, The following api I am using
executeOnExecutor(AsyncTask.THREAD_POOL_EXECUTOR,"nameofpool");
Is it possible that somehow I can set only 2 threads limit in this pool.

The AsyncTask.THREAD_POOL_EXECUTOR is a special pool that is created for you and administrated by Android.
You can, however, create your own Executor, typically using :
Executor myExecutor = Executors.newFixedThreadPool(2);
which you can use in your AsyncTask :
executeOnExecutor(myExecutor, params);
Nota: please note that your param "nameofpool" is actually the parameter to the doInBackground method on your AsyncTask, and is not related to the Thread pool management.

You can provide your own executor:
executeOnExecutor(Executors.newFixedThreadPool(2), "nameofpool");

Related

how to implement executors for splash screen in android

I read on post that Coroutine isn't a good practice for using on splash screen and Executors is the best for that because Coroutine takes a time to start more than Executors, but I didn't find an example of implementing that, is the Executors is the normal java Executor class which used to manage thread pool?
First, for splash best performance you must read the link mentioned in comments by William Reed here and here and also this other link here
and when you read the articles focus on these words
The measurements were made on a debuggable app differ surprisingly
from production performance
As pointed out by Jake Wharton, the difference is partly due to
ExecutorService being preloaded by the Zygote, a special part of the
Android framework that shares code between processes. Other
concurrency frameworks which, like coroutines, aren’t preloaded, will
also have a comparatively high initialization cost. That said,
coroutines have a lot of advantages over ExecutorService. They’ve got
scopes, suspending functions, they’re much more lightweight than
threads, etc. The general recommendation to use them in Android
applications is sound, but their impressive feature set has an
initialization cost at the moment. Perhaps the Kotlin and Android
teams will be able to optimize this in the future. Until then, best to
avoid using coroutines in your Application class, or in your main
Activity, if startup time is a primary concern.
Second, for your other part of the question I think that is the Executor you asked about
And here how to use it
1 - To execute code in the main thread
// Create an executor that executes tasks in the main thread.
val mainExecutor = ContextCompat.getMainExecutor(this)
// Execute a task in the main thread
mainExecutor.execute {
// You code logic goes here.
}
2 - To execute code in a background thread
// Create an executor that executes tasks in a background thread.
val backgroundExecutor: ScheduledExecutorService = Executors.newSingleThreadScheduledExecutor()
// Execute a task in the background thread.
backgroundExecutor.execute {
// Your code logic goes here.
}
// Execute a task in the background thread after 3 seconds.
backgroundExecutor.schedule({
// Your code logic goes here
}, 3, TimeUnit.SECONDS)
Remember to shut down the executor after using.
backgroundExecutor.shutdown(); // or backgroundExecutor.shutdownNow();
3 - To execute code in a background thread and update UI on the main thread.
// Create an executor that executes tasks in the main thread.
val mainExecutor: Executor = ContextCompat.getMainExecutor(this)
// Create an executor that executes tasks in a background thread.
val backgroundExecutor = Executors.newSingleThreadScheduledExecutor()
// Execute a task in the background thread.
backgroundExecutor.execute {
// Your code logic goes here.
// Update UI on the main thread
mainExecutor.execute {
// You code logic goes here.
}
}
what is the best for performance on Debug (Production May vary as mentioned before)?- Executor, and Coroutine takes much time based on trying both of them with this function
fun TestPerformance(){
val startTime = System.nanoTime()
// DEBUG in handler 3002952707
Handler(Looper.getMainLooper()).postDelayed({
val endTime = System.nanoTime()
println("DEBUG in handler ${endTime-startTime}")
}, 3000)
// DEBUG in backgroundExecutor 3001161822
val backgroundExecutor: ScheduledExecutorService = Executors.newSingleThreadScheduledExecutor()
backgroundExecutor.schedule({
val endTime = System.nanoTime()
println("DEBUG in backgroundExecutor ${endTime-startTime}")
}, 3, TimeUnit.SECONDS)
// DEBUG in GlobalScope 3046312603
GlobalScope.launch {
delay(3000)
val endTime = System.nanoTime()
println("DEBUG in GlobalScope ${endTime-startTime}")
}
}
As you can see I add another way to the comparison with handler too, and look at the comments in the code, both handler and Executor faster than Coroutine and sometimes handler wins and sometimes Executor wins, both of them gives the same performance.
and if you want more examples for how to use handler check this answer it's a great help and I used it in my answer.
once you have an Executor instance, you can submit multiple tasks to it, and have them executed one after another. You can't do that simply with a raw Thread.
Creates an Executor that uses a single worker thread operating off an unbounded queue. (Note however that if this single thread terminates due to a failure during execution prior to shutdown, a new one will take its place if needed to execute subsequent tasks.) Tasks are guaranteed to execute sequentially, and no more than one task will be active at any given time.
Executors.newSingleThreadExecutor().execute {
// todo.
}

When and why would one use a group of Executor

I have been reading about Executor in Android documentations. If I understood it correctly, it is used for multiple thread management and it does some of the work for you like spawning new threads when needed. Or you may choose to manage stuff yourself.
In the example below, a group of executors are used instead of one. So it is something like a pool of pool of threads (?).
/**
* Global executor pools for the whole application.
*
* Grouping tasks like this avoids the effects of task starvation (e.g. disk
reads don't wait behind
* webservice requests).
*/
#Singleton
open class AppExecutors(
private val diskIO: Executor,
private val networkIO: Executor,
private val mainThread: Executor
) {
#Inject
constructor() : this(
Executors.newSingleThreadExecutor(),
Executors.newFixedThreadPool(3),
MainThreadExecutor()
)
fun diskIO(): Executor {
return diskIO
}
fun networkIO(): Executor {
return networkIO
}
fun mainThread(): Executor {
return mainThread
}
private class MainThreadExecutor : Executor {
private val mainThreadHandler = Handler(Looper.getMainLooper())
override fun execute(command: Runnable) {
mainThreadHandler.post(command)
}
}
}
Why would one choose to use a group of executors? What do you achieve with it which you can't with just one executor?
That's just structuring and assigning the right executor for the right jobs they might execute:
It's nicely put in a single class for easy reuse.
Three types of executors are employed, each for a specific type of task it could run. Remember that executors have threads to execute jobs or Runnables and each thread the executor creates can run one job at a time:
diskIO is (from the constrcutor) a Executors.newSingleThreadExecutor() since the tasks are best queued and executed one at a time to reduce write and read locks or race conditions for example. Hence a SingleThreadExecutor would run only one task at a time no matter how many are queued to ensure that design. Being a single thread could also mean that it's being used for writing app logs to a file for example which allows for the logs to be written in the proper order as being submitted to the executor. Hence single thread is best at maintaining output as in the order of jobs queued.
networkIO is a Executors.newFixedThreadPool(3) since the tasks are usually network related like connecting to a server on the internet and performing requests or getting data. These tasks usually make the user wait (could be between seconds to minutes) and need to be executed in parallel and fast to make the wait shorter in case many requests need be performed together. Hence the reason there are 3 threads employed with this executor is to assign the tasks among them and execute together. Order of jobs is not a concern here since jobs take different amount of time to execute but what matters the most is that they're running in parallel.
mainThread is a MainThreadExecutor() which in an Android app handles the UI and drawing it. The UI should function smoothly and not lag and hence the reason to use the above two executors is to let any heavy task (like writing a file or performing requests) to run in the background or separately from the mainThread of the app. This executor keeps performing tasks even if the app didn't submit any to it. The tasks it keeps performing is drawing the UI continuously on the screen which constantly repeats. Tasks executed by the mainThread need to lightweight and fast (time they take are in the order of milliseconds), and so any task that slows it down will be noticed as the UI will lag or glitch with it because the mainThread is busy finishing that task instead of drawing and updating the UI. The mainThread here simply uses a Handler which is part of the Android SDK/architecture, is of a single thread type and behaves like an executor (with some differences) that queues tasks to create/update the UI. Only a Handler can perform UI tasks, none of the other executors can.

Set 'DiscardPolicy' on 'ThreadPool' created using 'ExecuteOnExecutor' method

I have a class called LoadEncryptedImage and that is derived from AsyncTask.
I used the below code to execute the async tasks in parallel,
LoadEncryptedImage loadEncryptedImage = new LoadEncryptedImage(mContext, eventMember.MemberPhotoURL,
viewHolder.imgUser);
loadEncryptedImage.executeOnExecutor(AsyncTask.THREAD_POOL_EXECUTOR);
It works properly, but it throws RejectedExecutionException if the tasks exceeds the limit of the ThreadPool. I want to set DiscardPolicy on ThreadPool to discard the issue silently. But how we can do this on a Threadpool created using ExecuteOnExecutor method.
But how we can do this on a Threadpool created using ExecuteOnExecutor method.
That is not a good idea. Do not change the characteristics of a thread pool that you did not create, as other things that depend upon that thread pool may not appreciate the changes that you make.
Instead, create your own ThreadPoolExecutor, with your desired characteristics, and pass that into executeOnExecutor().

Does AsyncTask run the doInBackground accordingly to each of its parameter order or randomly?

For example there is an AsyncTask of a String... parameters , if I make a call like this :
AsyncTask<String, Void, Void> someTask = new myTask(myActivity.this);
someTask.execute(string1 , string2 , string3);
What is the internal order of execution of the doInBackground inside this task : does it treat string1 first then string2 and so on sequencely as they are provided when called , or does it treat the parameters randomly ?
First thing, parameters are not passed randomly. This answer will explain you more about parameters. Also check image from this answer. I am adding same image here for your understanding.
It may be serial on one thread or parallel, it actually depends upon which version of Android OS your app is running. For most of the case it would be serial on one background thread.
This is what google document says :-
Executes the task with the specified parameters. The task returns itself (this) so that the caller can keep a reference to it.
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.
This method must be invoked on the UI thread.
Check this link execute (Params... params) it will help you.
Hope it helps,
Thanks.
String... is a "vararg", which in this example converts all individual parameters into a String[], where the entries to the array are in the order they got passed into the method.
So using your example, (String[]) param[0] == string1, param[1] == string2, param[2] == string3 and so forth. This is for the ordering of param entries, as to how each entry in param is used, it depends entirely on your code.

how to run AsyncTask parallelly or independently in android

I would like to send more than one request to server parallelly using AsyncTask in android
so how can i do that ?
I have seen code like
myAsync.executeOnExecutor(AsyncTask.THREAD_POOL_EXECUTOR, params)
but it is not running parallelly instead it is running serially.
please help me out.
Hey the executeonExecutor should work perfectly.
You will need to use a thread pool Executor to execute Asynctask . Default implementation uses a serial executor running on a single thread
So create a ThreadPoolExeecutor and then use
Asynctask's executeonExecutor instead of just execute method
There has been a change in AsyncTask from Honeycomb release. Older versions had a Thread pool of 10 threads, so you could run 10 tasks in parallel. But for Honeycomb and up, default is a serial executor, which executes tasks one by one. But you can pass a ThreadPoolExecutor for execution:
if (Build.VERSION.SDK_INT >= 11) {
//--post GB use serial executor by default --
task.executeOnExecutor(AsyncTask.THREAD_POOL_EXECUTOR);
} else {
//--GB uses ThreadPoolExecutor by default--
task.execute();
}
Create new instance of the async task and execute, then it will execute parallelly
simply... use
new YourAssynctask().execute();
this will indeed call your Assyntask's OnpreExecute() method.

Categories

Resources