kotlin之协程(一)

2023-07-15  本文已影响0人  Deck方

一、协程的挂起与恢复

suspend——也称为挂起或者暂停,用于暂定当前执行当前协程,并保存所有局部变量
resume——用于让暂定的协程从其暂定处继续执行

1.挂起函数

二、协程的两部分

三、协程的调度器

所有的协程必须在调度器中运行,即使他们在主线程上运行也是如此。

四、协程的任务泄露

五、协程构建器

1.launch月async构建器都用来启动新协程。

2.等待一个作业

  val duration = measureTimeMillis {
            val job1 = launch {
                delay(200)
                println("one finished")
            }
            job1.join()
            val job2 = launch {
                delay(200)
                println("two finished")
            }
            job2.join()
            val job3 = launch {
                delay(200)
                println("three finished")
            }
            job3.join()
        }
        println("join duration :${duration}")
   
val duration = measureTimeMillis {
            val job1 = async {
                delay(200)
                println("one finished")
                1
            }
            val job2 = async {
                delay(200)
                println("two finished")
                2
            }
            val job3 = async {
                delay(200)
                println("three finished")
                3
            }
            println("${job1.await()+job2.await()+job3.await()}")
        }
        println("duration :${duration}")

六、协程的启动模式

六、协程的作用域构建器

1.coroutineScope和runBlocking

七、Job对象

1、协程的取消
2.协程取消的副作用
3.不能取消的任务
4.超时任务
 val result = withTimeoutOrNull(5000L) {
   repeat(1000){
     println("im repeating")
   }
   "Done"
 }

八、协程的上下文

1.组合上下文中的元素
有时候我们需要在协程上下文中定义多个元素。我们可以使用+操作符来实现。比如我们可以显示指定一个调度器来启动协程并且同时显示指定一个命名:

   fun testCoroutineContext() = runBlocking<Unit> {
        launch(Dispatchers.Default + CoroutineName("test")) {
            println("Working in Thread ${Thread.currentThread().name}")
        }
    }

2.协程上下文的继承
a. 对于新的协程,它的CoroutineContext 会包含一个全新的Job实例,它会帮助我们控制协程的生命周期。而剩下的元素从CoroutineContext的父类继承,该父类可能是另外一个协程或者创建该协程的CoroutineScope。

fun testExtendCoroutineContext() = runBlocking<Unit> {
       val scope = CoroutineScope(Job() + Dispatchers.Default + CoroutineName("test"))
       val job = scope.launch {
           println("${coroutineContext[Job]}Working in Thread ${Thread.currentThread().name}")
           val result = async {
               println("${coroutineContext[Job]}Working in Thread ${Thread.currentThread().name}")
               "OK"
           }.await()
       }
       job.join()
   }

b. 协程的上下文 = 默认值+继承的CoroutineContext+参数

八、协程的异常处理

1、异常的传播:
协程构建器有两种形式:

fun testHandleException() = runBlocking<Unit> {
        val job = GlobalScope.launch {
            try {
                throw  IndexOutOfBoundsException()
            } catch (e: Exception) {
                println("catched IndexOutOfBoundsException")
            }
        }
        job.join()
        
        //async exception
        val deferred = GlobalScope.async {
            throw ArithmeticException()
        }
        try {
            //消费
            deferred.await()
        } catch (e: Exception) {
            println("cached ArithmeticException")
        }
    }
//直接抛出异常
 fun testHandleException2() = runBlocking<Unit> {
        val scope = CoroutineScope(Dispatchers.Default+CoroutineName("test"))
        val job = scope.launch {
            async {
                throw IndexOutOfBoundsException()
            }
        }
        job.join()
    }

2、异常传播的特性
当一个协程由于异常而运行失败时,它会传播这个异常并传递给它的父级。接下来父级会进行下面几个操作:

3、SupervisorJob
使用SupervisorJob时,一个子协程的运行失败不会影响其他子协程。SupervisorJob不会传播异常给它的父协程。

 fun testSupervisorJob() = runBlocking<Unit> {
        val supervisorScope =
            CoroutineScope(SupervisorJob() + Dispatchers.Default + CoroutineName("test"))
        val job1 = supervisorScope.launch {
            delay(1000)
            println("child 1")
            throw IndexOutOfBoundsException()
        }
        val job2 = supervisorScope.launch {
            try {
                delay(3000)
            } finally {
                println("child2 finish")
            }
        }
        joinAll(job1, job2)
    }
//最终结果是打印job1发生异常结束,但是job2正常执行

4、异常的捕获

 fun testExceptionSuppressed() = runBlocking<Unit> {
        val exceptionHandler = CoroutineExceptionHandler { _, exception ->
            println("Caught $exception ${exception.suppressed.contentToString()}")
        }
        val job = GlobalScope.launch(exceptionHandler) {

            launch {
                try {
                    delay(Long.MAX_VALUE)
                }finally {
                    throw ArithmeticException()
                }
            }
            launch {
                delay(100)
                throw IOException()
            }
        }
        job.join()
    }
//打印结果
//Caught java.io.IOException [java.lang.ArithmeticException]
上一篇 下一篇

猜你喜欢

热点阅读