RunBlocking for bridging in Kotlin - Time & Space Complexity
We want to understand how the time needed to run code changes when using runBlocking in Kotlin.
Specifically, how does waiting for coroutines inside runBlocking affect the total time?
Analyze the time complexity of the following code snippet.
import kotlinx.coroutines.*
fun main() = runBlocking {
repeat(5) { i ->
launch {
delay(100L)
println("Task $i done")
}
}
}
This code runs 5 coroutines inside runBlocking, each delaying 100 milliseconds before printing.
Identify the loops, recursion, array traversals that repeat.
- Primary operation: Launching 5 coroutines inside a loop.
- How many times: The loop runs 5 times, launching 5 separate tasks.
Each coroutine waits for a fixed delay, but they run at the same time inside runBlocking.
| Input Size (n) | Approx. Operations |
|---|---|
| 5 | 5 coroutines launched, total delay ~100ms |
| 10 | 10 coroutines launched, total delay ~100ms |
| 100 | 100 coroutines launched, total delay ~100ms |
Pattern observation: The total time stays about the same because coroutines run concurrently, not one after another.
Time Complexity: O(1)
The number of coroutines grows linearly with n (O(n)), but due to concurrency the total execution time remains constant O(1).
[X] Wrong: "All coroutines inside runBlocking run one after another, so total time is delay times number of coroutines."
[OK] Correct: Coroutines launched inside runBlocking run concurrently, so delays overlap and total time is closer to the longest single delay, not the sum.
Understanding how runBlocking manages coroutine execution helps you explain concurrency concepts clearly and shows you know how to bridge blocking and non-blocking code.
What if we replaced launch with async and awaited each result sequentially? How would the time complexity change?
Practice
runBlocking in Kotlin coroutines?Solution
Step 1: Understand the role of runBlocking
runBlocking is designed to bridge blocking and coroutine code by blocking the current thread until the coroutine inside it finishes.Step 2: Compare with other coroutine builders
Unlike launch or async, runBlocking blocks the thread, making it suitable for main functions or tests but not for UI or performance-critical code.Final Answer:
To bridge blocking code and coroutine code by blocking the current thread until coroutine completes -> Option DQuick Check:
runBlocking blocks thread until coroutine finishes = C [OK]
- Thinking runBlocking launches coroutine without blocking
- Confusing runBlocking with launch or async
- Assuming runBlocking creates a new thread
runBlocking in Kotlin?Solution
Step 1: Recall runBlocking syntax
runBlocking is a function that takes a lambda block inside curly braces to run coroutine code.Step 2: Identify correct syntax
runBlocking { println("Hello") } uses curly braces correctly with a lambda block. Other options use invalid syntax like parentheses with arrow or square brackets.Final Answer:
runBlocking { println("Hello") } -> Option CQuick Check:
runBlocking uses curly braces for lambda = A [OK]
- Using parentheses instead of curly braces
- Using arrow or square brackets incorrectly
- Missing lambda block inside runBlocking
import kotlinx.coroutines.*
fun main() = runBlocking {
launch {
delay(100)
println("World")
}
println("Hello")
}Solution
Step 1: Understand runBlocking and launch behavior
runBlocking blocks the main thread until all coroutines inside complete. The launch coroutine delays 100ms before printing "World".Step 2: Trace the print statements
"Hello" is printed immediately in runBlocking, then after 100ms delay, "World" is printed by the launched coroutine.Final Answer:
Hello World -> Option AQuick Check:
runBlocking waits; launch delays; prints Hello then World = D [OK]
- Assuming launch runs immediately before println("Hello")
- Ignoring delay effect
- Thinking runBlocking does not wait for launch
runBlocking:
fun main() {
runBlocking {
delay(1000)
println("Done")
}
}Solution
Step 1: Check for necessary imports
The delay function is part of kotlinx.coroutines package and requires import kotlinx.coroutines.delay.Step 2: Verify usage of runBlocking and delay
runBlocking can be used inside main, and delay is allowed inside runBlocking coroutine scope, so no error there.Final Answer:
Missing import for delay function -> Option BQuick Check:
delay needs import kotlinx.coroutines.delay = A [OK]
- Thinking runBlocking can't be used in main
- Assuming delay is a blocking call
- Placing println outside runBlocking unnecessarily
runBlocking. Which code correctly achieves this?Solution
Step 1: Understand runBlocking usage for sequential delay
fun main() = runBlocking { for (i in 1..3) { delay(500) println(i) } } uses runBlocking once and delays inside a for loop, printing numbers sequentially with 500ms delay.Step 2: Analyze other options
fun main() { for (i in 1..3) { delay(500) println(i) } } lacks a coroutine scope, so delay() will not compile. fun main() = runBlocking { (1..3).forEach { launch { delay(500); println(it) } } } launches coroutines concurrently, printing numbers out of order. fun main() { (1..3).forEach { Thread.sleep(500) println(it) } } uses Thread.sleep, which blocks thread but not coroutine style.Final Answer:
fun main() = runBlocking { for (i in 1..3) { delay(500) println(i) } } -> Option AQuick Check:
runBlocking with sequential delay in loop = B [OK]
- Using runBlocking inside loop repeatedly
- Launching coroutines without waiting
- Using Thread.sleep instead of delay in coroutines
Ready to prove it?
Pass the test and this pattern moves unknown
