Kotlin协程简介(一)

本文深入探讨了Kotlin协程的基础概念与应用,包括runBlocking、suspend、coroutine的使用,以及cancel、timeout等控制机制。通过具体示例,解析了不同协程构造函数的行为差异,展示了如何管理和控制协程的执行流程。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

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”

 

 

 

 

 

 

 

 

 

 

 

 

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值