AndroidBites: #2 Threads: Create, Start, Schedule, Prioritize

Image for post
Image for post

Hello everyone! this is a small series I’m starting on Android Development where I will try to break down the small core programming concepts into key points and bite-size snippets which you can use to brush up your concepts!

Keep learning and Happy Hacking!

In Android, we have lots of mechanisms to start off an asynchronous task.

Threads and Runnables, HandlerThreads / Eventloop — MessageQueue, Executors, and ThreadPoolExecutor, Loaders, and AsyncLoaders , Async Task , Futures , Rxjava , Coroutines and many more…

Most of you would be going with Rxjava and Coroutines but knowing all other concepts will help you appreciate newer frameworks more, also they are important for interviews.

We are covering Concept of Threads, this is a continuation of the First Part, in case you missed it Part#1 starts from here.

Threads

There are two ways to create a new thread.

  • One is to declare a class to be a subclass of Thread
  • The other way to create a thread is to declare a class that implements the Runnable interface.

Subclassing Thread

class SimpleThread : Thread() {    init {
try {
this.start()
} catch (e: InterruptedException) {
println(e.localizedMessage)
}
}
//there are no checked exceptions in Kotlin
@Throws(InterruptedException::class)
override fun run() {
super.run()
for (i in 1..10) {
println("Hello: $i from ${Thread.currentThread().name}")
sleep(1000) //in MilliSeconds
}
}
}
fun main(args: Array<String>) {
SimpleThread() // thread obj creation + call
}
//===== OR ==================================================fun main(args: Array<String>) {// abstracting everthing away in lambda
val thread = Thread {
for (i in 1..10) {
println("Hello: $i from ${Thread.currentThread().name}")
Thread.sleep(1000) //in MilliSeconds
}
}
thread.start()
}

Implements the Runnable interface

fun main(args: Array<String>) {
Thread(WithRunnable()).start()
}
class WithRunnable : Runnable {
@Throws(InterruptedException::class)
override fun run() {
for (i in 1..10) {
println("Hello: $i from ${Thread.currentThread().name}")
Thread.sleep(1000) //in MilliSeconds
}
}
}
//===== OR ==================================================fun main(args: Array<String>) {
ThreadWithRunnable(Runnable {
for (i in 1..10) {
println("Hello: $i from ${Thread.currentThread().name}")
Thread.sleep(1000) //in MilliSeconds
}
})
}
class ThreadWithRunnable(runnable: Runnable) : Thread(runnable) {
init {
try {
this.start()
} catch (e: InterruptedException) {
println(e.localizedMessage)
}
}
}

Thread Class vs Runnable Interface

  1. If we extend the Thread class, our class cannot extend any other class because Java/Kotlin doesn’t support multiple inheritance.
  2. But, if we implement the Runnable interface, our class can still extend other base classes, this is why Runnable method is recommended for thread creation.
  3. Extending Thread class provides us some inbuilt methods like yield(), interrupt() etc. that are not available in Runnable interface.

…knowing about thread API functions such as start(), run(), interrupt() is quite important we will discuss on them more in-depth later!

In the above examples, you see start() method starts off the thread and its executed immediately. I have used Thread.currentThread().name to set thread names.

If I perform the below snippet can you guess which thread would be running first?

fun main(args: Array<String>) {
SimpleThread() // Thread.currentThread().name = "SimpleThreading"
ThreadWithRunnable(Runnable {
for (i in 1..10) {
Thread.currentThread().name = "ThreadWithRunnable"
println("Hello: $i from ${Thread.currentThread().name}")
Thread.sleep(1000) //in MilliSeconds
}
})
Thread {
for (i in 1..10) {
Thread.currentThread().name = "LambdaThreading"
println("Hello: $i from ${Thread.currentThread().name}")
Thread.sleep(1000) //in MilliSeconds
}
}.start()
}

Answer :

it depends! , the possible output could be:

  1. SimpleThreading, ThreadWithRunnable, LambdaThreading
  2. ThreadWithRunnable, LambdaThreading, SimpleThreading
  3. LambdaThreading, ThreadWithRunnable, SimpleThreading
  4. and other combos…

Why is that? because of Thread scheduling…

Thread Scheduler

Thread scheduler is the part of the JVM that decides which thread should run.

  • There is no guarantee that which runnable thread will be chosen to run by the thread scheduler.
  • Only one thread at a time can run in a single cpu core.
  • The thread scheduler mainly uses preemptive or time-slicing scheduling to schedule the threads.
  • In preemptive scheduling, the highest priority task executes until it enters the waiting or dead states or a higher priority task comes into existence.
  • In time slicing, a task executes for a predefined slice of time and then reenters the pool of ready tasks. The scheduler then determines which task should execute next, based on priority and other factors.

From here you see, for getting a thread its turn concept of Thread Priority becomes important… let’s dig into it

Thread Priority

thread schedular schedules the threads according to their priority if JVM chooses preemptive scheduling

  • Priorities are represented by a number between 1 and 10.
  • Thread Class has Commonly used Constant Name for them: MIN_PRIORITY (1) , NORM_PRIORITY(5) ,MAX_PRIORITY(10)
  • you can set a thread priority using <ThreadObject>.setPriority(value:Int)
  • Thread with the highest priority will get execution chance prior to other threads.
  • The default priority is always NORM_PRIORITY, which can be updated later
  • The default priority for all other threads depends on the priority of parent thread.
  • If two threads have the same priority then we can’t expect which thread will execute first. It depends on thread scheduler’s algorithm(Round-Robin, First Come First Serve, etc)
  • If we are using thread priority for thread scheduling then we should always keep in mind that the underlying platform should provide support for scheduling based on thread priority.

Thread Scheduler in Android

Thread Scheduler in Android is almost the same as in any JVM machine, it uses two main factors to determine how threads are scheduled across the entire system: nice values and cgroups.

Nice values

They have a lower priority and are called nice values since they have lower priorities they are being “nice” to other threads in the system.

Cgroups

Stands for Control groups. They are Linux container that manages the allocation of processor time for all threads in one container.

Android defines multiple cgroups, but the most important ones for applications are Foreground and Background Group (CPU for Foreground groups > Background groups).

Thread Priority in Android

  • In Android we have two ways to set priority to threads : Thread.setPriority() and Process.setThreadPriority().
  • Thread.setPriority() is similar to basic JVM threads from 0 to 10 but Process.setThreadPriority() varies supports value from -20 to 19.
  • Thread.setPriority actually do the same thing as Process.setThreadPriority, Process.setThreadPriority just use smaller Java priority scale in order to respect background and foreground task.

Here is the mapping from Thread class priority to Process class Priority

Image for post
Image for post

END

This is for today! We covered Thread Creation, Starting and Scheduling, In the next article, we will look into Lifecycle of threads and Some Thread API functions.

Written by

Coding enthusiast! love Android #kotlinAlltheWay, want to explore all opportunity around it! CodingMantra: #cleanCoder #TDD #SOLID #designpatterns

Get the Medium app

A button that says 'Download on the App Store', and if clicked it will lead you to the iOS App store
A button that says 'Get it on, Google Play', and if clicked it will lead you to the Google Play store