Startup of Kotlin coroutines
Article directory
- Kotlin coroutine startup
-
- Add dependency
- Debug coroutine
- Start coroutine
-
- GlobalScope.launch
- launch
- runBlocking
- async-await
- The difference between launch and async
- Summary
Kotlin coroutine start
Add dependencies
implementation 'org.jetbrains.kotlinx:kotlinx-coroutines-core:1.6.0'
Debugging coroutines
Set VM parameters
Set VM parameters: -Dkotlinx.coroutines.debug
, you can bring coroutine related information when outputting Thread.currentThread().name
.
Format:
@#
Breakpoint debugging
View Kotlinversion:
Break point: Check suspend and All, which means it will take effect for the coroutine
You can view the Coroutines panel information: the current coroutine name is “coroutine:1”, running on the “”DefaultDispatcher-worker-1″” thread, and the current state is “RUNNING”.
Start the coroutine
GlobalScope.launch
fun main() {
GlobalScope. launch {
println("The coroutine starts to execute")
delay(1000L)
println("The coroutine is finished")
}
println("A")
Thread. sleep(2000L)
println("B")
}
//A
//The coroutine starts to execute
//The coroutine is executed
//B
Adding Thread.sleep(2000L)
is to prevent the execution of the main thread before the execution of the coroutine, and the program has ended.
This is because the thread that GlobalScope.launch
depends on is a daemon thread, and it will be destroyed after the main thread exits.
launch
public fun CoroutineScope.launch(
context: CoroutineContext = EmptyCoroutineContext,
start: CoroutineStart = CoroutineStart. DEFAULT,
block: suspend CoroutineScope.() -> Unit
): Job {
...
}
CoroutineScope.launch()
: launch is actually an extension function, is a member method of CoroutineScope. GlobalScope is a CoroutineScope object provided by Kotlin.
The first parameter CoroutineContext
: indicates the context of the coroutine, the default value is EmptyCoroutineContext. Can be used to specify information about coroutines.
The second parameter CoroutineStart
: indicates the start mode of the coroutine.
- DEFAULT: Default value, execute immediately.
- LAZY: Lazy loading execution.
The third parameter suspend CoroutineScope.() -> Unit
: block of function type, the main body of the task executed by the coroutine.
run Blocking
The coroutine started with runBlocking
will block the current thread.
fun main() {
runBlocking {
println("The coroutine starts to execute")
delay(1000L)
println("The coroutine is finished")
}
println("A")
Thread. sleep(2000L)
println("B")
}
//The coroutine starts to execute
//The coroutine is executed
//A
//B
Note: Do not use runBlocking
in a production environment.
async-await
Coroutines created using async
have a return value. After starting the coroutine, the current execution process will not be blocked. The await()
function can receive the return value, and the receiving process will perform “suspend” and “resume”.
fun main() {
runBlocking {
println("The coroutine starts to execute")
val deferred: Deferred = async {
println("async start: ${Thread.currentThread().name}")
delay(1000L)
return @async "hello"
}
println("async end: ${Thread.currentThread().name}")
val result = deferred. await()
println("result: $result")
println("The coroutine is finished")
}
}
//The coroutine starts to execute
//async end: main @coroutine#1
//async start: main @coroutine#2
//result: hello
//The coroutine is executed
The difference between launch and async
public fun CoroutineScope.async(
context: CoroutineContext = EmptyCoroutineContext,
start: CoroutineStart = CoroutineStart. DEFAULT,
block: suspend CoroutineScope.() -> T
): Deferred {
...
}
async
Compared with launch
, the return value type of the former block parameter is T, and the latter is Unit; the return value of the function is the former type of Deferred, and the latter is of type Job, and Deferred inherits from Job.
fun main() = runBlocking {
suspend fun getName(): String {
delay(1000L)
return "Xiao Ming"
}
suspend fun getAge(): Int {
delay(2000L)
return 18
}
suspend fun getAddress(): String {
delay(3000L)
return "Beijing"
}
val results = mutableListOf()
val time = measureTimeMillis {
results. add(getName())
results. add(getAge())
results. add(getAddress())
}
println("time-consuming: $time")
println(results)
}
//Time-consuming: 6009
//[Xiao Ming, 18, Beijing]
fun main() = runBlocking {
suspend fun getName(): String {
delay(1000L)
return "Xiao Ming"
}suspend fun getAge(): Int {
delay(2000L)
return 18
}
suspend fun getAddress(): String {
delay(3000L)
return "Beijing"
}
var results = listOf()
val time = measureTimeMillis {
val result1 = async { getName() }
val result2 = async { getAge() }
val result3 = async { getAddress() }
results = listOf(result1. await(), result2. await(), result3. await())
}
println("time-consuming: $time")
println(results)
}
//Time-consuming: 3024
//[Xiao Ming, 18, Beijing]
If there is a dependency relationship, use the suspend function to connect directly; if there is no dependency relationship, use async to connect in parallel.
Summary
Start mode | Is blocking | Returning results | Application scenario |
---|---|---|---|
launch | No | No | Fire-and-forget |
runBlocking | Yes | Yes | Test Environment |
async-await | No | Yes | Get the result of the coroutine execution |