📖 Scenario: Imagine you are organizing a small bakery. You have two ways to handle orders: either hire many bakers (threads) who each work independently, or have a few bakers who can quickly switch tasks without waiting (coroutines).
🎯 Goal: You will create a simple Kotlin program to understand how coroutines differ from threads by simulating tasks that print messages with delays. This will help you see how coroutines are lightweight and efficient compared to threads.
📋 What You'll Learn
Create a thread that prints a message after a delay
Create a coroutine that prints a message after a delay
Use a configuration variable to set the delay time
Print the outputs to compare thread and coroutine behavior
💡 Why This Matters
🌍 Real World
Coroutines help apps stay responsive by doing many tasks without blocking the main work, like handling multiple bakery orders smoothly.
💼 Career
Understanding coroutines vs threads is key for Kotlin developers building efficient, fast, and responsive applications.
Progress0 / 4 steps
1
Create a thread that prints a message after a delay
Create a Thread named threadExample that waits for 1000 milliseconds and then prints "Thread: Baking bread". Start the thread.
Kotlin
Hint
Use Thread { ... } to create a thread and Thread.sleep(1000) to wait 1 second.
2
Add a delay configuration variable
Create an Int variable called delayTime and set it to 1000. Use this variable in the Thread.sleep() call inside threadExample.
Kotlin
Hint
Define delayTime before the thread and replace the fixed 1000 with delayTime.
3
Create a coroutine that prints a message after a delay
Import kotlinx.coroutines.*. Create a runBlocking block. Inside it, launch a coroutine named coroutineExample that delays for delayTime milliseconds and then prints "Coroutine: Baking bread".
Kotlin
Hint
Use runBlocking to start coroutines in main, then launch to create a coroutine.
4
Print the final output to compare thread and coroutine
Add a println statement after starting the thread and launching the coroutine that prints "Main: Bakery is open". This shows the main program continues without waiting.
Kotlin
Hint
Print "Main: Bakery is open" right after starting the thread to see the main thread is not blocked.
Practice
(1/5)
1. Which statement best describes the difference between Kotlin coroutines and threads?
easy
A. Both coroutines and threads are managed by the OS and have the same weight.
B. Threads are lightweight and managed by Kotlin, coroutines are heavier and managed by the OS.
C. Coroutines are lightweight and managed by Kotlin, threads are heavier and managed by the OS.
D. Coroutines and threads are the same and can be used interchangeably without difference.
Solution
Step 1: Understand management of coroutines and threads
Coroutines are managed by Kotlin's runtime, making them lightweight tasks.
Step 2: Understand thread management
Threads are managed by the operating system and are heavier compared to coroutines.
Final Answer:
Coroutines are lightweight and managed by Kotlin, threads are heavier and managed by the OS. -> Option C
Quick Check:
Coroutines lightweight, threads OS-managed = A [OK]
Hint: Coroutines are Kotlin tasks; threads are OS tasks [OK]
Common Mistakes:
Confusing which manages coroutines vs threads
Thinking coroutines are OS threads
Assuming threads are lightweight like coroutines
2. Which Kotlin code snippet correctly launches a coroutine?
easy
A. coroutineStart { println("Start") }
B. Thread { println("Hello from thread") }.start()
C. runBlocking { Thread.sleep(1000) }
D. launch { println("Hello from coroutine") }
Solution
Step 1: Identify coroutine launch syntax
The correct way to start a coroutine in Kotlin is using the 'launch' builder inside a coroutine scope.
Step 2: Check other options for correctness
Thread { println("Hello from thread") }.start() starts a thread, not a coroutine. runBlocking { Thread.sleep(1000) } uses runBlocking with Thread.sleep, which blocks a thread. coroutineStart { println("Start") } is invalid syntax.
Final Answer:
launch { println("Hello from coroutine") } -> Option D
Quick Check:
launch starts coroutine = A [OK]
Hint: Use 'launch' to start coroutines, not Thread or unknown keywords [OK]
Common Mistakes:
Using Thread instead of launch for coroutines
Confusing runBlocking with coroutine launch
Using invalid coroutine syntax
3. What will be the output of this Kotlin code snippet?
Step 1: Understand runBlocking and launch behavior
runBlocking blocks the main thread until its coroutine completes. The launch coroutine delays 100ms before printing.
Step 2: Trace output order
"Main finished" prints immediately. After 100ms delay, "Coroutine finished" prints. runBlocking waits for launch to complete before exiting.
Final Answer:
Main finished
Coroutine finished -> Option A
Quick Check:
runBlocking waits, delay delays launch = C [OK]
Hint: runBlocking waits; launch delays print [OK]
Common Mistakes:
Assuming launch runs before main print
Ignoring delay effect
Thinking runBlocking doesn't wait
4. Identify the error in this Kotlin coroutine code:
fun main() {
launch {
println("Hello")
}
}
medium
A. Missing coroutine scope to launch coroutine
B. Incorrect use of println inside coroutine
C. launch should be replaced with Thread
D. No error, code runs fine
Solution
Step 1: Check coroutine launch context
launch must be called inside a coroutine scope or suspend function. Here, main is a regular function without scope.
Step 2: Identify missing coroutine scope
Without a scope like runBlocking or CoroutineScope, launch cannot start a coroutine.
Final Answer:
Missing coroutine scope to launch coroutine -> Option A
Quick Check:
launch needs coroutine scope = B [OK]
Hint: launch needs coroutine scope like runBlocking [OK]
Common Mistakes:
Trying to launch coroutine outside scope
Replacing launch with Thread incorrectly
Thinking println causes error
5. You want to perform multiple network calls concurrently without blocking the main thread. Which approach best uses Kotlin coroutines to achieve this?
hard
A. Create multiple threads and use Thread.sleep to wait for results
B. Launch multiple coroutines with async and await their results
C. Use a single coroutine and call blocking network functions sequentially
D. Run network calls on the main thread directly
Solution
Step 1: Understand concurrency with coroutines
Using async inside coroutines allows concurrent execution and returns Deferred results.
Step 2: Compare options for efficiency and correctness
Create multiple threads and use Thread.sleep to wait for results uses threads and blocking sleep, which is heavy and inefficient. Use a single coroutine and call blocking network functions sequentially blocks sequentially, losing concurrency. Run network calls on the main thread directly blocks main thread, causing UI freeze.
Final Answer:
Launch multiple coroutines with async and await their results -> Option B
Quick Check:
async + await = concurrent coroutines [OK]
Hint: Use async/await for concurrent coroutines, not threads [OK]
Common Mistakes:
Using threads with sleep instead of coroutines
Blocking main thread with network calls
Running network calls sequentially inside one coroutine
Recommended
Ready to prove it?
Pass the test and this pattern moves unknownstrongwhile earning +1 Grip toward your certificate.