user1443721
user1443721

Reputation: 1260

Does GlobalScope.launch create a new thread or run in the same thread?

I have the question from this code.

https://kotlinlang.org/docs/reference/coroutines/basics.html

fun main() {
    GlobalScope.launch { // launch new coroutine in background and continue
        delay(1000L) // non-blocking delay for 1 second (default time unit is ms)
        println("World!") // print after delay
    }
    println("Hello,") // main thread continues while coroutine is delayed
    Thread.sleep(2000L) // block main thread for 2 seconds to keep JVM alive
}

I replace delay(1000L) with Thread.sleep(1000L). If GlobalScope.launch block will run in the same thread, the Thread.sleep(1000L) will block the thread. However it seems not.

fun main() {
    GlobalScope.launch { // launch new coroutine in background and continue
        Thread.sleep(1000L)
        println("World!")
    }
    println("Hello,") // 
    Thread.sleep(2000L) // block main thread for 2 seconds to keep JVM alive
} 

Upvotes: 6

Views: 4513

Answers (3)

s1m0nw1
s1m0nw1

Reputation: 81899

The GlobalScope lets you start coroutines which more-or-less have the same behavior as daemon threads since they are detached from any Coroutine-Job and basically run as long as the application. Their lifecycle is only limited by the application itself. This is something you want to avoid by using "structured concurrency" which basically means that your coroutines should be nested in a way that you can control them without manually keeping track of their references and joining them for example in order to await their computations. So in your real-life code you should avoid GlobalScope as much as possible, since there's most certainly a better solution.

As to your question, and as already mentioned, the GlobalScope runs on the Dispatchers.Default pool, which means that you will block some worker thread but not the one you spawned the coroutine from.

On the other hand, if you were to write this block:

fun main() {
    runBlocking { 
        Thread.sleep(1000L) 
        println("World!") 
    }
    println("Hello,") 
    Thread.sleep(2000L) 
}

you'll see that the coroutine blocks the main thread and the output will show a different result. That is because runBlocking runs on the caller thread main rather than one of the worker pool threads.

Upvotes: 4

Joffrey
Joffrey

Reputation: 37700

GlobalScope.launch { } will not necessarily create a new thread, but it will use one from a shared pool because it uses the Default dispatcher. So, as far as your question is concerned, in your snippet, the block passed to launch runs in a different thread indeed.

In the documentation about dispatchers and threads, you will find the following:

The default dispatcher, that is used when coroutines are launched in GlobalScope, is represented by Dispatchers.Default and uses shared background pool of threads

And in the Dispatchers.Default doc, you can find:

By default, the maximal level of parallelism used by this dispatcher is equal to the number of CPU cores, but is at least two. Level of parallelism X guarantees that no more than X tasks can be executed in this dispatcher in parallel.

Note that you could change the dispatcher by providing one as a parameter of launch.

Upvotes: 1

Eugene Petrenko
Eugene Petrenko

Reputation: 4992

The GlobalScope.launch{..} function will not block. It returns an Job object, which you may use to wait for a result.

Behind the scenes, the GlobalScope uses the default dispatcher Dispatchers.Default. You may see it, for example, by printing a thread name inside a launch{..} function.

You will need to run more coroutines to see them blocking each other because of Thread.sleep calls.

https://kotlinlang.org/docs/reference/coroutines/coroutine-context-and-dispatchers.html

Upvotes: 0

Related Questions