Your first coroutine
|
import kotlinx.coroutines.*
fun main() {
GlobalScope.launch { // launch a 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
}
|
import kotlinx.coroutines.*
func main() {
GlobalScope.launch { // launch a new coroutine in background and continue
delay(1000L) // non-blocking delay for 1 second (default time unit is ms)
print("World!") // print after delay
}
print("Hello,") // main thread continues while coroutine is delayed
Thread.sleep(2000L) // block main thread for 2 seconds to keep JVM alive
}
|
Bridging blocking and non-blocking worlds
|
import kotlinx.coroutines.*
fun main() {
GlobalScope.launch { // launch a new coroutine in background and continue
delay(1000L)
println("World!")
}
println("Hello,") // main thread continues here immediately
runBlocking { // but this expression blocks the main thread
delay(2000L) // ... while we delay for 2 seconds to keep JVM alive
}
}
|
import kotlinx.coroutines.*
func main() {
GlobalScope.launch { // launch a new coroutine in background and continue
delay(1000L)
print("World!")
}
print("Hello,") // main thread continues here immediately
runBlocking { // but this expression blocks the main thread
delay(2000L) // ... while we delay for 2 seconds to keep JVM alive
}
}
|
import kotlinx.coroutines.*
fun main() = runBlocking<Unit> { // start main coroutine
GlobalScope.launch { // launch a new coroutine in background and continue
delay(1000L)
println("World!")
}
println("Hello,") // main coroutine continues here immediately
delay(2000L) // delaying for 2 seconds to keep JVM alive
}
|
import kotlinx.coroutines.*
func main() = runBlocking<Unit> { // start main coroutine
GlobalScope.launch { // launch a new coroutine in background and continue
delay(1000L)
print("World!")
}
print("Hello,") // main coroutine continues here immediately
delay(2000L) // delaying for 2 seconds to keep JVM alive
}
|
class MyTest {
@Test
fun testMySuspendingFunction() = runBlocking<Unit> {
// here we can use suspending functions using any assertion style that we like
}
}
|
class MyTest {
@Test
func testMySuspendingFunction() = runBlocking<Unit> {
// here we can use suspending functions using any assertion style that we like
}
}
|
Waiting for a job
|
val job = GlobalScope.launch { // launch a new coroutine and keep a reference to its Job
delay(1000L)
println("World!")
}
println("Hello,")
job.join() // wait until child coroutine completes
|
let job = GlobalScope.launch { // launch a new coroutine and keep a reference to its Job
delay(1000L)
print("World!")
}
print("Hello,")
job.join() // wait until child coroutine completes
|
Structured concurrency
|
import kotlinx.coroutines.*
fun main() = runBlocking { // this: CoroutineScope
launch { // launch a new coroutine in the scope of runBlocking
delay(1000L)
println("World!")
}
println("Hello,")
}
|
import kotlinx.coroutines.*
func main() = runBlocking { // this: CoroutineScope
launch { // launch a new coroutine in the scope of runBlocking
delay(1000L)
print("World!")
}
print("Hello,")
}
|
Scope builder
|
import kotlinx.coroutines.*
fun main() = runBlocking { // this: CoroutineScope
launch {
delay(200L)
println("Task from runBlocking")
}
coroutineScope { // Creates a coroutine scope
launch {
delay(500L)
println("Task from nested launch")
}
delay(100L)
println("Task from coroutine scope") // This line will be printed before the nested launch
}
println("Coroutine scope is over") // This line is not printed until the nested launch completes
}
|
import kotlinx.coroutines.*
func main() = runBlocking { // this: CoroutineScope
launch {
delay(200L)
print("Task from runBlocking")
}
coroutineScope { // Creates a coroutine scope
launch {
delay(500L)
print("Task from nested launch")
}
delay(100L)
print("Task from coroutine scope") // This line will be printed before the nested launch
}
print("Coroutine scope is over") // This line is not printed until the nested launch completes
}
|
Extract function refactoring
|
import kotlinx.coroutines.*
fun main() = runBlocking {
launch { doWorld() }
println("Hello,")
}
// this is your first suspending function
suspend fun doWorld() {
delay(1000L)
println("World!")
}
|
import kotlinx.coroutines.*
func main() = runBlocking {
launch { doWorld() }
print("Hello,")
}
// this is your first suspending function
suspend func doWorld() {
delay(1000L)
print("World!")
}
|
Coroutines ARE light-weight
|
import kotlinx.coroutines.*
fun main() = runBlocking {
repeat(100_000) { // launch a lot of coroutines
launch {
delay(5000L)
print(".")
}
}
}
|
import kotlinx.coroutines.*
func main() = runBlocking {
repeat(100_000) { // launch a lot of coroutines
launch {
delay(5000L)
print(".")
}
}
}
|
Global coroutines are like daemon threads
|
GlobalScope.launch {
repeat(1000) { i ->
println("I'm sleeping $i ...")
delay(500L)
}
}
delay(1300L) // just quit after delay
|
GlobalScope.launch {
repeat(1000) { i ->
print("I'm sleeping $i ...")
delay(500L)
}
}
delay(1300L) // just quit after delay
|