Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Why Kotlin coroutines run in the same thread sequentially?

I thought that calling a "suspend" function from coroutine context using launch makes the call asynchronous. But in the example below I see that 2 invocations of placeOrder method are not running in the same thread one after another. What is my mistake?

import kotlinx.coroutines.launch
import kotlinx.coroutines.runBlocking
import java.io.File

fun main() = runBlocking {
    t("1")
    launch {
        t("2")
        placeOrder("C:\\Users")
        t("3")
    }
    launch {
        t("12")
        placeOrder("C:\\Program Files")
        t("13")
    }
    t("4")
}


fun t(s: String) {
    val currentThread = Thread.currentThread()
    println(s + ": " + currentThread.name + " " +     currentThread.id)
}

suspend fun placeOrder(d:String): String {
    t("placeOrder $d")
    val user = createUser(d) // asynchronous call to user service
    val order = createOrder(user) // asynchronous call to order service
    t("placeOrder $d finished")
    return order
}

suspend fun createUser(d:String): String {
    t("createUser $d")
    val toString = File(d).walk().map {
        it.length()
    }.sum().toString()
    t("createUser $d finished")
    return toString
}

suspend fun createOrder(user: String): String {
    t("createOrder $user")
    val toString = File("C:\\User").walk().map {
        it.length()
    }.sum().toString()
    t("createOrder $user finished")
    return toString
}

Output:

1: main 1
4: main 1
2: main 1
placeOrder C:\Users: main 1
createUser C:\Users: main 1
createUser C:\Users finished: main 1
createOrder 1094020270277: main 1
createOrder 1094020270277 finished: main 1
placeOrder C:\Users finished: main 1
3: main 1
12: main 1
placeOrder C:\Program Files: main 1
createUser C:\Program Files: main 1
createUser C:\Program Files finished: main 1
createOrder 5651227104: main 1
createOrder 5651227104 finished: main 1
placeOrder C:\Program Files finished: main 1
13: main 1
like image 955
Pavel Bernshtam Avatar asked Apr 15 '19 13:04

Pavel Bernshtam


People also ask

Are coroutines sequential?

by default the methods are executed sequentially one after another. N.B:- codes are sequentially executed within a coroutine by default.

Does a coroutine run on a different thread?

Coroutines and/or generators can be used to implement cooperative functions. Instead of being run on kernel threads and scheduled by the operating system, they run in a single thread until they yield or finish, yielding to other functions as determined by the programmer.

Do coroutines in Kotlin allocate new threads?

Kotlin Coroutines Creating too many threads can actually make an application underperform in some situations; threads are objects which impose overhead during object allocation and garbage collection. To overcome these issues, Kotlin introduced a new way of writing asynchronous, non-blocking code; the Coroutine.

Are coroutines single threaded?

coroutines , which can be used for iOS, supports usage only in a single thread. You cannot send work to other threads by changing a dispatcher. For Kotlin 1.7.


Video Answer


1 Answers

Instead of writing suspendable IO, you wrote blocking IO:

File(d).walk().map {
    it.length()
}

Your functions never actually suspend and instead they block the single thread associated with their runBlocking dispatcher.

You gave your coroutines no opportunity to execute concurrently.

If you applied withContext(IO) { ... } around the above code, you'd get concurrency, but of the plain-old Java type, several threads being blocked in IO operations together.

like image 105
Marko Topolnik Avatar answered Sep 23 '22 01:09

Marko Topolnik