delay vs Thread.sleep

Suspending vs Blocking

delay() suspends the coroutine and frees the thread. Thread.sleep() blocks the whole thread, so no other coroutine on that thread can run.

Example

Three coroutines on the single runBlocking thread. With delay they overlap; with Thread.sleep they run one by one.

import kotlinx.coroutines.*
import kotlin.system.measureTimeMillis

fun main() = runBlocking {
    val withDelay = measureTimeMillis {
        coroutineScope { repeat(3) { launch { delay(200) } } }
    }
    val withSleep = measureTimeMillis {
        coroutineScope { repeat(3) { launch { Thread.sleep(200) } } }
    }
    println("delay: about 200 ms -> ${withDelay in 200..450}")
    println("Thread.sleep: at least 600 ms -> ${withSleep >= 600}")
}

Output

delay: about 200 ms -> true
Thread.sleep: at least 600 ms -> true

Common Builders at a Glance

FunctionKindWaits for childrenReturns
runBlockingblocking bridgeyesblock result
launchnew coroutine-Job
asyncnew coroutine-Deferred<T>
coroutineScopesuspend functionyesblock result
supervisorScopesuspend functionyesblock result
withContextsuspend functionyesblock result
producecoroutine + channel-ReceiveChannel<T>

Tip: Inside a coroutine never call blocking functions (Thread.sleep, blocking JDBC, File.readText on a big file) on Dispatchers.Main or Default. Wrap them in withContext(Dispatchers.IO).