10kotlin之协程(二)

kotlin之协程(二)

1.协程地取消与超时

isActive,隐含了CoroutineScope,本身是挂起函数。 当取消时,使用它的位置,遇到挂起函数,自动计算协程状态

package day8Coroutines


import kotlinx.coroutines.*

/**
 * 协程取消时,有一种情况,是无法取消的, 该函数正在计算中
 * 取消的原理,只有当遇到挂起函数时,会自动计算当前协程状态
 *
 */
fun main(args: Array<String>) {
    runBlocking {
        var myJob = GlobalScope.launch {  //suspend CoroutineScope.() -> Unit
            repeat(200) { //重复0 - 200,可以用来做定时
                println("$it")
                delay(500)
            }
            isActive  //隐含了CoroutineScope
        }
        delay(1000)
        println("你好")
        myJob.cancel()
        myJob.join()
        println("欢迎")
    }
}

2.取消正在计算的协程

密集型计算,会导致线程卡死,相应线程中的协程根本不会执行。导致协程不能取消。

package day8Coroutines

import kotlinx.coroutines.*

/**
 * 正在
 */
fun main(args: Array<String>) {
    runBlocking {
        var job = launch(Dispatchers.Default) {
            var count = 0
            try {
                while (isActive) {
                    count++
                }
            } finally {
                println("世界安静了")
            }
        }
        delay(1000)

        /**
         * 下面这种方式会导致卡死,原因是delay先执行,然后程序一直在做空轮转,导致线程卡死。线程中的协程根本不会执行
         */
//        var job = launch() {
//            var count = 0
//            while (isActive) {
//                count++
//            }
//        }
        delay(200)
        println("开始")
        job.cancelAndJoin()
        println("结束")
    }
}

3.取消协程案例

多个withConext是串行执行。本质原因是withConext是一个挂起函数。

withContext{}不会创建新的协程,在指定协程上运行挂起代码块,并挂起该协程直至代码块运行完成。简单说,就是在已有(并非原有)协程上挂起。

package day8Coroutines

import kotlinx.coroutines.*

/**
 * 使用withContext函数 来解决取消协程的问题
 */
fun main(args: Array<String>) {
    runBlocking {
        var job = launch(Dispatchers.Default) {
            var count = 0
            try {
                while (isActive) {
                    count++
                }
            } finally {
//                println("世界安静了") // 这里就已经结束了
//                delay(1000) //这一段执行时,会直接抛出CancellationException异常,后面就不会执行了
//                println("新的一天开始了") //这一段不会开始,原因是,该协程已经取消了,大多数情况都不会发生阻塞,比如网络情况,那么解决这种问题了

                /**
                 * 开启一个新的协程,NonCancellable默认不会取消的协程
                 */
                withContext(NonCancellable) {
                    println("世界安静了")
                    delay(1000)
                    println("新的一天开始了")
                }
            }
        }
        delay(1000)
        delay(200)
        println("开始")
        job.cancelAndJoin()
        println("结束")
    }
}

4.withTimeOut超时协程取消

package day8Coroutines

import kotlinx.coroutines.isActive
import kotlinx.coroutines.runBlocking
import kotlinx.coroutines.withTimeout

/**
 * 超时时,可以手动取消协程,也可以使用kotlin中提供的内奸函数来帮助我们解决问题
 * 注意:正在计算中的协程依旧无法取消
 *
 */
fun main(args: Array<String>) {
    runBlocking {
        withTimeout(1900) {
//            repeat(100) {
//                println("$it")
//                delay(100)
//            }

            var count = 0
            try {
                while (isActive) {
                    count++
                }
            } finally {
                println("世界安静了")
            }
        }
    }
}

5.withTimeOutOrNull协程超时

package day8Coroutines

import kotlinx.coroutines.*

/**
 * 如果使用如果使用withTimeout,则需要使用try catch 捕捉CancellationException异常
 * 更好的方式,是使用withTimeoutOrNukk,类似与如果使用withTimeout,但不会抛出CancellationException异常,而是直接返回null
 * withTimeout和是使用withTimeoutOrNull是一个挂起函数
 *
 *
 */
fun main(args: Array<String>) {
    runBlocking {
        try {
            withTimeout(1900) {
                repeat(100) {
                    println("$it")
                    delay(100)
                }
            }
        } catch (e: CancellationException) {
        }

        var result = withTimeoutOrNull(2000) {
            repeat(100) {
                println("$it")
                delay(100)
            }
        }
        println("$result")
    }
}

6.协程并发

采用挂起函数来串行执行。

package day8Coroutines

import kotlinx.coroutines.*
import java.lang.Exception
import kotlin.system.measureTimeMillis

/**
 * 协程并发
 * 1.下面中方式,在开发中基本不会使用到,使用挂起函数来顺序执行,
 * 缺陷:如果initValue()发生异常,那么initValue2()不会执行
 * 2:这种方式的并不是真正的并发
 *
 */
fun main(args: Array<String>) {
    runBlocking {
//        try {
//            val time = measureTimeMillis {
//                val value = initValue()
//                val value2 = initValue2()
//                println("结果:${value + value2}")
//            }
//        } catch (e: Exception) {
//
//        }
        initValue3()
        initValue4()

    }
}

private suspend fun initValue(): Int {
    delay(2000)
    return 20
}

private suspend fun initValue2(): Int {
    delay(2000)
    return 50
}

fun initValue3(): Job = GlobalScope.launch {
    delay(100)
    initValue()
}

fun initValue4(): Job = GlobalScope.launch {
    delay(100)
    initValue2()
}

7.async和await实现更加合理的并发

async:它会开启一个新的协程.会返回一个Deffered非阻塞的future

await:挂起函数,会阻塞协程。

package day8Coroutines

import kotlinx.coroutines.async
import kotlinx.coroutines.delay
import kotlinx.coroutines.runBlocking
import kotlin.system.measureTimeMillis

/**
 * 在kotlin中,async和await并不是关键字,只是扩展函数
 * async:同launch一样,它会开启一个新的协程区别是,会返回一个Deffered非阻塞的future,可以稍后获取结果值
 * await:挂起函数,会阻塞协程
 */
fun main(args: Array<String>) {
    runBlocking {
        val time = measureTimeMillis {
            val v1 = async {
                initValue()
            }
            val v2 = async {
                initValue2()
            }
            //实现了并发,获取值
            var result1 = v1.await()
            var result2 = v2.await()
            println("${result1 + result2}")
        }
    }
}

private suspend fun initValue(): Int {
    delay(2000)
    return 20
}

private suspend fun initValue2(): Int {
    delay(2000)
    return 50
}
    var result1 = v1.await()
        var result2 = v2.await()
        println("${result1 + result2}")
    }
}

}

private suspend fun initValue(): Int {
delay(2000)
return 20
}

private suspend fun initValue2(): Int {
delay(2000)
return 50
}


  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值