This article will cover thread pools, thread pool executors, and their use within Android. We’ll cover these topics thoroughly, with lots of example code.
A thread pool manages a pool of worker threads (the exact number varies depending upon how it’s implementation).
A task queue holds tasks waiting to be executed by any one of the idle threads in the pool. Tasks are added to the queue by producers, whereas the worker threads act as consumers by consuming the tasks from the queue whenever there’s an idle thread ready to perform a new background execution.
The ThreadPoolExecutor executes a given task using one of its threads from the thread pool.
ThreadPoolExecutor threadPoolExecutor = new ThreadPoolExecutor(
What are these parameters ?
- corePoolSize: The minimum number of threads to keep in the pool. Initially there are zero threads in the pool. But as tasks are added to the queue, new threads are created. If there are idle threads — but the thread count is lower than the corePoolSize — then new threads will keep on being created.
- maximumPoolSize: The maximum number of threads allowed in the pool. If this exceeds the corePoolSize — and the current number of threads is >= corePoolSize — then new worker threads will be created only if the queue is full.
- keepAliveTime: When the number of threads is greater than the core, the noncore threads (excess idle threads) will wait for a new tasks, and if they don’t get one within the time defined by this parameter, they will terminate.
- unit: The unit of time for keepAliveTime.
- workQueue: The task queue, which will only hold runnable tasks. It will have to be a BlockingQueue.
Why use Thread Pool Executor in an Android or JAVA application?
- It’s a powerful task execution framework as it supports task addition in a queue, task cancellation, and task prioritization.
- It reduces the overhead associated with thread creation, as it manages a required number of threads in its thread pool.
Using ThreadPoolExecutor in Android
First of all, create a PriorityThreadFactory:
Create a MainThreadExecutor:
Create a DefaultExecutorSupplier:
Note: The number of threads available for different thread pools will depend on your requirements.
Now use it as below in your code.
In this way, we can create a different thread pool for network tasks, I/O tasks, heavy background tasks, and other tasks.
How do I cancel a task?
To cancel a task, you have to get the future of that task. So instead of using execute, you would need to use submit, which will return a future. Now, this future can be used to cancel the task.
How to set the priority of a task?
Let’s say there are 20 tasks in a queue, and the thread pool only holds 4 threads. We execute new tasks based on their priority, since the thread pool can only execute 4 at a time.
But let’s say we need the last task that we have pushed in the queue to be executed first. We would need to set the IMMEDIATE priority for that task so that when the thread takes new task from the queue, it executes this task first (since it has the highest priority).
To set the priority of a task, we need to create a thread pool executor.
Create an ENUM for Priority:
Create a PriorityRunnable:
Create a PriorityThreadPoolExecutor, which extends ThreadPoolExecutor. We have to create PriorityFutureTask, which will implement Comparable<PriorityFutureTask>
First of all, in DefaultExecutorSupplier, instead of ThreadPoolExecutor, use PriorityThreadPoolExecutor like this:
Here’s an example of how we can set HIGH priority to a task:
In this way, a task can be prioritized.
The above implementation is also applicable for any JAVA applications.
I used this thread pool implementation in Android Networking Library.
For more detail implementation, you can check out the DefaultExecutorSupplier.java class of Android Networking here.
I hope this will be useful for you.