Kotlin协程简介
1、runBlocking、suspend、coroutine
1.1、最简单的列子:
@Test
fun runMainBlocking() = runBlocking <Unit>{
val job = GlobalScope.launch {
delay(1000L)
println("World!")
}
print("Hello ")
job.join()
}
输出:
Hello World!
Process finished with exit code 0
以上方法可以简化为:
@Test
fun runMainBlocking1() = runBlocking<Unit> {
launch {//简化写法
delay(1000L)
println("World!")
}
println("Hello ")
}
其中runBlocking为suspend方法,
1.2、当调用其他挂起方法时:
@Test
fun runMain2() = runBlocking {
launch { doWorld() }
println("Hello ")
}
suspend fun doWorld(){
delay(100L)
println("World!")
}
1.3 runBlocking和coroutine函数
@Test
fun runMain() = runBlocking {
println("Task from begin")
launch {
delay(100L)
println("Task from blocking")
}
launch {
delay(100L)
println("Task from blocking 2")
}
coroutineScope {//挂起不会阻塞
launch {
delay(100L)
println("Task from nested launch")
}
delay(100L)
println("Task from coroutineScope")
}
launch {
delay(100L)
println("Task from blocking 3")
}
runBlocking {//阻塞
launch {
delay(100L)
println("Task from blocking launch")
}
delay(100L)
println("Task from runBlocking")
}
println("Coroutine scope is over")
}
打印值:
Task from begin
Task from coroutineScope
Task from blocking
Task from blocking 2
Task from nested launch
Task from blocking 3
Task from runBlocking
Task from blocking launch
Coroutine scope is over
Process finished with exit code 0
runBlocking方法里遇到coroutineScope suspend方法后,回到最开始的launch开始执行,执行到corortine后继续执行后者,遇到runBlocking之前,其线程被阻塞,lacunch顺序执行(注意区别)。
2.cancel、timeouts
2.1、cancelAndJoin
@Test
fun main() = runBlocking {
val startTime = System.currentTimeMillis()
var job = launch(Dispatchers.Default) {
println("launch current thread is " + Thread.currentThread().name)
var nextTime = startTime
var i = 0
while (i < 5) {
if (System.currentTimeMillis() >= nextTime) {
println("job: I'm sleeping ${i++}")
nextTime += 500L
}
}
}
println("current thread is " + Thread.currentThread().name)
delay(1600L)
println("main:I'm tried to waiting")
job.cancelAndJoin()
println("main:Now i can quit")
}
输出:
current thread is main @coroutine#1
launch current thread is DefaultDispatcher-worker-1 @coroutine#2
job: I'm sleeping 0
job: I'm sleeping 1
job: I'm sleeping 2
job: I'm sleeping 3
main:I'm tried to waiting
job: I'm sleeping 4
main:Now i can quit
Process finished with exit code 0
由上可见1、launch(Dispatchers.Default)方法使其进入到了工作线程;2、cancelAndJoin()方法会阻塞直到工作线程执行完,才继续后续方法(cancel()方法将直接跳过,不会阻塞)。
2.2、NonCancellable
@Test
fun main1() = runBlocking {
val job = launch {
println("launch current thread is " + Thread.currentThread().name)
try {
repeat(1000) { i ->
println("job:I'm sleeping $i")
delay(500L)
println("repeat current thread is " + Thread.currentThread().name)
}
} finally {
withContext(NonCancellable) {
println("withContext current thread is " + Thread.currentThread().name)
println("I'm running finally")
delay(1000L)
println("job:And I've just delayed for 1 sec because I'm NonCancellable ")
}
}
}
println("current1 thread is " + Thread.currentThread().name)
delay(1300L)
println("main:I'm tried to waiting")
job.cancelAndJoin()
println("current2 thread is " + Thread.currentThread().name)
println("main:Now i can quit")
}
输出:
current1 thread is main @coroutine#1
launch current thread is main @coroutine#2
job:I'm sleeping 0
repeat current thread is main @coroutine#2
job:I'm sleeping 1
repeat current thread is main @coroutine#2
job:I'm sleeping 2
main:I'm tried to waiting
withContext current thread is main @coroutine#2
I'm running finally
job:And I've just delayed for 1 sec because I'm NonCancellable
current2 thread is main @coroutine#1
main:Now i can quit
Process finished with exit code 0
由此可见:整个执行过程在主线程中,repeat方法被cancelAndJoin方法取消,而NonCancellable方法可以无视cancelAndJoin方法,cancelAndJoin方法将会阻塞线程,直到NonCancellable执行完毕。
2.3、withTimeoutOrNull
@Test
fun main3() = runBlocking {
var result: Unit? = null
launch(Dispatchers.Default) {
result = withTimeoutOrNull(2000) {
repeat(10) {
println("I'm sleeping $it")
delay(500L)
}
}
println("result is $result")
}
println("result is $result")
println("This is main")
}
输出:
result is null
This is main
I'm sleeping 0
I'm sleeping 1
I'm sleeping 2
I'm sleeping 3
result is null
Process finished with exit code 0
由此可见,withTimeoutOrNull方法(毫秒)执行到预定时间后,如果工作线程没有执行完成,那么返回null,否则返回“kotlin.Unit”