Search icon CANCEL
Arrow left icon
Explore Products
Best Sellers
New Releases
Books
Videos
Audiobooks
Learning Hub
Conferences
Free Learning
Arrow right icon
Arrow up icon
GO TO TOP
Learning Concurrency in Kotlin

You're reading from   Learning Concurrency in Kotlin Build highly efficient and scalable applications

Arrow left icon
Product type Paperback
Published in Jul 2018
Publisher Packt
ISBN-13 9781788627160
Length 266 pages
Edition 1st Edition
Languages
Concepts
Arrow right icon
Author (1):
Arrow left icon
Miguel Angel Castiblanco Torres Miguel Angel Castiblanco Torres
Author Profile Icon Miguel Angel Castiblanco Torres
Miguel Angel Castiblanco Torres
Arrow right icon
View More author details
Toc

Table of Contents (11) Chapters Close

Preface 1. Hello, Concurrent World! 2. Coroutines in Action FREE CHAPTER 3. Life Cycle and Error Handling 4. Suspending Functions and the Coroutine Context 5. Iterators, Sequences, and Producers 6. Channels - Share Memory by Communicating 7. Thread Confinement, Actors, and Mutexes 8. Testing and Debugging Concurrent Code 9. The Internals of Concurrency in Kotlin 10. Other Books You May Enjoy

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.

lock icon The rest of the chapter is locked
Register for a free Packt account to unlock a world of extra content!
A free Packt account unlocks extra newsletters, articles, discounted offers, and much more. Start advancing your knowledge today.
Unlock this book and the full library FREE for 7 days
Get unlimited access to 7000+ expert-authored eBooks and videos courses covering every tech area you can think of
Renews at €18.99/month. Cancel anytime