user10314481
user10314481

Reputation:

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?

Upvotes: 4

Views: 1478

Answers (1)

ahasbini
ahasbini

Reputation: 6891

That's just structuring and assigning the right executor for the right jobs they might execute:

  1. It's nicely put in a single class for easy reuse.
  2. 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.

Upvotes: 7

Related Questions