Apps/Gaming

Getting started with Kotlin coroutines

Asynchronous processing is one of the indispensable functions that every single programming language has. Asynchronous functions come in many formats, styles, and rules, regardless of whether they are built in or extended by various external libraries.

When it comes to the world of the Java Virtual Machine (JVM), Java threads absolutely ruled for many years. When Kotlin first came out, it decided to simplify the process (as with many other JVM functions) of managing asynchronous code through coroutines.

For example, if you’ve worked with JavaScript before, you may know the most popular reserved keywords for it: async and await – the former is used to identify the asynchronous block of code and the latter to wait for it to complete.

In Kotlin, these keywords are not part of the standard library, so developers are required to import the kotlinx.coroutines library in order to use it. In addition to this, Kotlin also offers other keywords like launch, coroutineScope, runBlocking and more.

In this article, we’re going to take the first steps to understand how Kotlin deals with asynchronous programming via coroutines. Let’s get into that!

Read: Introduction to Kotlin

What is a Kotlin Coroutine?

The best way to understand something is to play around with it. So let’s come straight to an example. Note the following Kotlin code:

fun main () = runBlocking {doWorld ()} suspend fun doWorld () = coroutineScope {// this: CoroutineScope launch {delay (1000L) println (“World!”)} println (“Hello”)}

This code snippet was extracted from the official Kotlin documents page. Here is the usual main () function, which starts execution, followed by a block of runBlocking code.

In simple terms, a coroutine is a child of an unhookable function. It’s very similar to working with threads in other languages, which means that execution is happening at the same time as the rest of the non-asynchronous code.

That being said, it is very important to know about Kotlin coroutines that they are not tied to a specific thread, which means that a coroutine will start and stop execution from a specific thread, and then immediately resume execution in another completely different thread can, for example.

In the example above we have some key actors such as:

  • runBlocking: This is a coroutine builder that draws a line that separates the synchronous world from the asynchronous code that is executing within the block of code. In other words, if you want something to be done asynchronously, this builder provides that functionality.
  • coroutineScope: This is very similar to runBlocking in that it is also waiting for its body (and children) to complete. The difference, however, is that it doesn’t block code execution like runBlocking, but instead halts the thread so it is available for other synchronous processing that may need to be performed.
    Another special feature of this function is that when other external functions are called, it always requires this function to be marked as suspendable using the suspend operator.
  • launch: This is another coroutine builder that tells the rest of the code to continue executing as the body of the launch is running in parallel.
  • delay: This is also a suspending function very similar to Java’s Thread.sleep, which means that execution will pause for the specified time. Note, however, that this can only be done in asynchronous areas, which means that the rest of the synchronous execution will run normally.

As a Result of the above execution, we printed “Hello” on the first line, followed by “World!” – to prove that synchronization execution will always continue no matter how much asynchronous processing you get in your code.

Read: Top 5 Online IDEs and Code Editors

Working with jobs in Kotlin

ONE Background job is a cancelable piece of code with a lifecycle that ends when it is completed. Jobs can have a status throughout their lifecycle: child jobs that can be recursively canceled, error control, and other functions.

Every time you call a launch builder, they return a job that can be used to wait for the coroutine to complete or, if necessary, cancel it.

Let’s look at a sample job in Kotlin:

val job = launch {// start a new coroutine and keep a reference to your job delay (1000L) println (“World!”)} println (“Hello”) job.join () // wait for the subordinate coroutine to finish is println (“done”)

As you can see, the object reference can later be used to wait for the inner coroutines to complete using the join () function. This is a very simple feature when you want to leave this control to other parts of the code.

The same could be applied if you want to cancel it:

job.cancel ()

Time out in Kotlin

There is another great feature that comes with coroutines related to timeouts. When performing asynchronous operations, it is very important to be aware of potentially indefinite data flows because they can use up your available memory very quickly and lead to widespread errors in your application.

Every Java developer should be aware of the infamous OutOfMemoryError – great care should be taken to avoid it. If you are unfamiliar with this, it is a bug that occurs in Java programs when the JVM can no longer allocate a particular object because of a lack of space in the Java heap or insufficient native memory to handle the loading of a. to support java class.

Kotlinx offers an easy way to fix this problem using the withTimeout () function, shown below:

withTimeout (2000L) {retry (100) {delay (500L)}}

Whenever the operation exceeds the set limit of milliseconds, a CancellationException error is thrown.

Another useful function to avoid this type of error is withTimeoutOrNull, which halts execution for the specified timeout and returns zero to the caller if it is exceeded.

The “async” keyword in Kotlin

As you might guess, Kotlin offers one too asynchronous keyword for asynchronous processing. The async function creates coroutines and returns the “future” result as Deferred, which is a job with a result.

It sounds like it’s a lot like the launch, doesn’t it? However, it works by creating a completely separate, lightweight, thread-based coroutine that runs in parallel with everyone else.

Other than that, startup functions are invalid, which means we cannot extract future results from them, unlike asynchronous functions that can. Since these are jobs too, developers can cancel them later if necessary.

Consider the following example which shows how to use asynchronous in Kotlin:

runBlocking {val one = async {“One”} val two = async {“Two”} println (“Results: $ {one.await ()}, $ {two.await ()}”)}

Both of the asynchronous blocks of code run in parallel, and you need to explicitly call the await () function if you want to access its results as soon as they are ready (which in turn depends on how much processing time is in your asynchronous blocks).

It’s worth noting that these blocks of code must also be present in pending functions if you want to distribute them outside of runBlocking.

Read: Best Practices for Asynchronous Programming in Java

Conclusion on Kotlin Coroutines

There’s a lot more complexities you can learn with Kotlin Coroutines that we couldn’t easily address here, so we’ll leave it to that official documents and future Kotlin tutorials to fill in the blanks.

Remember that in addition to the pure use of coroutines in your Kotlin projects, you can also integrate other platforms such as Spring Boot.

If you’re working with client / server apps, you probably want some kind of asynchronous processing at some point. Official projects like theFor example, take coroutines from the ground up to be the best way to get your goals into code.

Related posts

Teamwork Project Management Review

TechLifely

Stack and Heap Memory in Java

TechLifely

Java Best Practices

TechLifely

Leave a Comment