Book Image

Learning Concurrency in Kotlin

By : Castiblanco Torres
Book Image

Learning Concurrency in Kotlin

By: Castiblanco Torres

Overview of this book

Kotlin is a modern and statically typed programming language with support for concurrency. Complete with detailed explanations of essential concepts, practical examples and self-assessment questions, Learning Concurrency in Kotlin addresses the unique challenges in design and implementation of concurrent code. This practical guide will help you to build distributed and scalable applications using Kotlin. Beginning with an introduction to Kotlin's coroutines, you’ll learn how to write concurrent code and understand the fundamental concepts needed to write multithreaded software in Kotlin. You'll explore how to communicate between and synchronize your threads and coroutines to write collaborative asynchronous applications. You'll also learn how to handle errors and exceptions, as well as how to work with a multicore processor to run several programs in parallel. In addition to this, you’ll delve into how coroutines work with each other. Finally, you’ll be able to build an Android application such as an RSS reader by putting your knowledge into practice. By the end of this book, you’ll have learned techniques and skills to write optimized code and multithread applications.
Table of Contents (11 chapters)

Concepts and terminology

To end this chapter, we will cover some basic concepts and terminology when talking about concurrency in Kotlin; these are important in order to more clearly understand the upcoming chapters.

Suspending computations

Suspending computations are those computations that can suspend their execution without blocking the thread in which they reside. Blocking a thread is often inconvenient, so by suspending its own execution, a suspending computation allows the thread to be used for other computations until they need to be resumed.

Because of their nature, suspending computations can only be invoked from other suspending functions or from coroutines.

Suspending functions

Suspending functions are suspending computations in the shape of a function. A suspending function can be easily identified because of the modifier suspend. For example:

suspend fun greetAfter(name: String, delayMillis: Long) {
delay(delayMillis)
println("Hello, $name")
}

In the previous example, the execution of greetAfter() will be suspended when delay() is called – delay() is a suspending function itself, suspending the execution for a give duration. Once delay() has been completed, greetAfter() will resume its execution normally. And while greetAfter() is suspended, the thread of execution may be used to do other computations.

In Chapter 9, The Internals of Concurrency in Kotlin, we will talk about how this works behind the scenes.

Suspending lambdas

Similar to a regular lambda, a suspending lambda is an anonymous local function. The difference is that a suspending lambda can suspend its own execution by calling other suspending functions.

Coroutine dispatcher

In order to decide what thread to start or resume a coroutine on, a coroutine dispatcher is used. All coroutine dispatchers must implement the CoroutineDispatcher interface:

  • DefaultDispatcher: Currently it is the same as CommonPool. In the future, this may change.
  • CommonPool: Executes and resumes the coroutines in a pool of shared background threads. Its default size makes it optimal for use in CPU-bound operations.
  • Unconfined: Starts the coroutine in the current thread (the thread from which the coroutine was invoked), but will resume the coroutine in any thread. No thread policy is used by this dispatcher.

Along with these dispatchers, there are a couple of builders that can be used to define pools or threads as needed:

  • newSingleThreadContext() to build a dispatcher with a single thread; the coroutines executed here will be started and resumed in the same thread, always.
  • newFixedThreadPoolContext() creates a dispatcher with a pool of threads of the given size. The runtime will decide which thread to use when starting and resuming the coroutines executed in the dispatcher.

Coroutine builders

A coroutine builder is a function that takes a suspending lambda and creates a coroutine to run it. Kotlin provides many coroutine builders that adjust to many different common scenarios, such as:

  • async(): Used to start a coroutine when a result is expected. It has to be used with caution because async() will capture any exception happening inside the coroutine and put it in its result. Returns a Deferred<T> that contains either the result or the exception.
  • launch(): Starts a coroutine that doesn't return a result. Returns a Job that can be used to cancel its execution or the execution of its children.
  • runBlocking(): Created to bridge blocking code into suspendable code. It's commonly used in main() methods and unit tests. runBlocking() blocks the current thread until the execution of the coroutine is completed.

Here is an example of async():

val result = async { 
isPalindrome(word = "Sample")
}
result.await()

In this example, async() is executed in the default dispatcher. It is possible to manually specify the dispatcher:

val result = async(Unconfined) {
isPalindrome(word = "Sample")
}
result.await()

In this second example, Unconfined is used as the dispatcher of the coroutine.