| Builder | Returns | Blocks thread | Waits completion | Root Job | New Job | New coroutine |
|---|---|---|---|---|---|---|
| runBlocking() (plug, rarely used) |
block result | ✓ Yes | ✓ Yes | ✓ Yes CEH doesn't work | ✓ Yes | ✓ Yes |
| withContext(Dispatcher...) | block result | ✗ No | ✓ Yes | ✗ No | ✗ No | ✗ No |
| coroutineScope { } | block result | ✗ No | ✓ Yes | ✗ No | ✓ Yes | ✓ Yes |
| supervisorScope { } | block result | ✗ No | ✓ Yes |
✗ No
CEH works for children |
✓ Yes SupervisorJob | ✓ Yes |
| GlobalScope. ... { } (e.g., GlobalScope.launch { }) |
Job/Deffered | ✗ No | ✗ No | ✓ Yes | ✓ Yes | ✓ Yes |
| launch() / async() | Job/Deffered | ✗ No | ✗ No | ✗ No | ✓ Yes | ✓ Yes |
|
launch(Job()) / async(Job())
⚠️ anti-pattern
breaks structured concurrency
|
Job/Deffered | ✗ No | ✗ No |
✓ Yes
passed Job() becomes root
CEH works for launch, NOT for async |
✓ Yes | ✓ Yes |
| Expression | Returns | Blocks thread | Waits completion | Root Job | New Job | New coroutine |
|---|---|---|---|---|---|---|
| val my = CoroutineScope() | CoroutineScope(Job()) | CoroutineScope(SupervisorJob()) |
itself | ✗ No | ✗ No | ✓ Yes gets/creates root | ✓ Yes | ✗ No |