<output id="qn6qe"></output>

    1. <output id="qn6qe"><tt id="qn6qe"></tt></output>
    2. <strike id="qn6qe"></strike>

      亚洲 日本 欧洲 欧美 视频,日韩中文字幕有码av,一本一道av中文字幕无码,国产线播放免费人成视频播放,人妻少妇偷人无码视频,日夜啪啪一区二区三区,国产尤物精品自在拍视频首页,久热这里只有精品12

      kotlin協(xié)程——>異常處理

      異常處理

         本節(jié)內(nèi)容涵蓋了異常處理與在異常上取消。我們已經(jīng)知道取消協(xié)程會在掛起點(diǎn)拋出 CancellationException 并且它會被協(xié)程的機(jī)制所忽略。在這?我們會看看在取消過程中拋出異常或同 ?個協(xié)程的多個?協(xié)程拋出異常時會發(fā)?什么。

       

      異常的傳播

        協(xié)程構(gòu)建器有兩種形式:?動傳播異常(launch 與 actor)或向??暴露異常(async 與 produce)。當(dāng) 這些構(gòu)建器?于創(chuàng)建?個根協(xié)程時,即該協(xié)程不是另?個協(xié)程的?協(xié)程,前者這類構(gòu)建器將異常視為未 捕獲異常,類似 Java 的 Thread.uncaughtExceptionHandler,?后者則依賴??來最終消費(fèi)異 常,例如通過 await 或 receive(produce 與 receive 的相關(guān)內(nèi)容包含于通道章節(jié))。 可以通過?個使? GlobalScope 創(chuàng)建根協(xié)程的簡單?例來進(jìn)?演?:

      import kotlinx.coroutines.*
      fun main() = runBlocking {
          val job = GlobalScope.launch { // launch 根協(xié)程
              println("Throwing exception from launch")
              throw IndexOutOfBoundsException() // 我們將在控制臺打印
              Thread.defaultUncaughtExceptionHandler
          }
          job.join()
          println("Joined failed job")
          val deferred = GlobalScope.async { // async 根協(xié)程
              println("Throwing exception from async")
              throw ArithmeticException() // 沒有打印任何東西,依賴??去調(diào)?等待
          }
          try {
              deferred.await()
              println("Unreached")
          } catch (e: ArithmeticException) {
              println("Caught ArithmeticException")
          }
      }
      

        這段代碼的輸出如下(調(diào)試):

      Throwing exception from launch
      Exception in thread "DefaultDispatcher-worker-2 @coroutine#2"
      java.lang.IndexOutOfBoundsException
      Joined failed job
      Throwing exception from async
      Caught ArithmeticException
      

        

      CoroutineExceptionHandler

        It is possible to customize the default behavior of printing uncaught exceptions to the console. CoroutineExceptionHandler context element on a root coroutine can be used as generic catch block for this root coroutine and all its children where custom exception handling may take place. It is similar to Thread.uncaughtExceptionHandler. You cannot recover from the exception in the CoroutineExceptionHandler . The coroutine had already completed with the corresponding exception when the handler is called. Normally, the handler is used to log the exception, show some kind of error message, terminate, and/or restart the application. 在 JVM 中可以重定義?個全局的異常處理者來將所有的協(xié)程通過 ServiceLoader 注冊到 CoroutineExceptionHandler。全局異常處理者就如同 Thread.defaultUncaughtExceptionHandler ?樣,在沒有更多的指定的異常處理者被注冊的 時候被使?。在 Android 中,uncaughtExceptionPreHandler 被設(shè)置在全局協(xié)程異常處理者中。

        CoroutineExceptionHandler is invoked only on uncaught exceptions — exceptions that were not handled in any other way. In particular, all children coroutines (coroutines created in the context of another Job) delegate handling of their exceptions to their parent coroutine, which also delegates to the parent, and so on until the root, so the CoroutineExceptionHandler installed in their context is never used. In addition to that, async builder always catches all exceptions and represents them in the resulting Deferred object, so its CoroutineExceptionHandler has no effect either

      Coroutines running in supervision scope do not propagate exceptions to their parent and are excluded from this rule. A further Supervision section of this document gives more details.
      

        

      val handler = CoroutineExceptionHandler { _, exception ->
          println("CoroutineExceptionHandler got $exception")
      }
      val job = GlobalScope.launch(handler) { // root coroutine, running in GlobalScope
          throw AssertionError()
      }
      val deferred = GlobalScope.async(handler) { // also root, but async instead of launch
          throw ArithmeticException() // 沒有打印任何東西,依賴??去調(diào)? deferred.await()
      }
      joinAll(job, deferred)
      

        這段代碼的輸出如下:

      CoroutineExceptionHandler got java.lang.AssertionError
      

        

      取消與異常

        取消與異常緊密相關(guān)。協(xié)程內(nèi)部使? CancellationException 來進(jìn)?取消,這個異常會被所有的 處理者忽略,所以那些可以被 catch 代碼塊捕獲的異常僅僅應(yīng)該被?來作為額外調(diào)試信息的資源。當(dāng) ?個協(xié)程使? Job.cancel 取消的時候,它會被終?,但是它不會取消它的?協(xié)程。

      val job = launch {
          val child = launch {
              try {
                  delay(Long.MAX_VALUE)
              } finally {
                  println("Child is cancelled")
              }
          }
          yield()
          println("Cancelling child")
          child.cancel()
          child.join()
          yield()
          println("Parent is not cancelled")
      }
      job.join()
      

        這段代碼的輸出如下:

      Cancelling child
      Child is cancelled
      Parent is not cancelled
      

        如果?個協(xié)程遇到了 CancellationException 以外的異常,它將使?該異常取消它的?協(xié)程。這 個?為?法被覆蓋,并且?于為結(jié)構(gòu)化的并發(fā)(structured concurrency)提供穩(wěn)定的協(xié)程層級結(jié)構(gòu)。 CoroutineExceptionHandler 的實(shí)現(xiàn)并不是?于?協(xié)程。

      在本例中,CoroutineExceptionHandler 總是被設(shè)置在由 GlobalScope 啟動的協(xié)程中。將異常處理者設(shè)置在 runBlocking 主作?域內(nèi)啟動的協(xié)程中是沒有意義的,盡管?協(xié)程已經(jīng)設(shè)置了異常處理者,但是主協(xié)程也總是會被取消的。
      

        當(dāng)?協(xié)程的所有?協(xié)程都結(jié)束后,原始的異常才會被?協(xié)程處理,?下?這個例?

      val handler = CoroutineExceptionHandler { _, exception ->
          println("CoroutineExceptionHandler got $exception")
      }
      val job = GlobalScope.launch(handler) {
          launch { // 第?個?協(xié)程
              try {
                  delay(Long.MAX_VALUE)
              } finally {
                  withContext(NonCancellable) {
                      println("Children are cancelled, but exception is not handled until all
                              children terminate")
                              delay(100)
                              println("The first child finished its non cancellable block")
                  }
              }
          }
          launch { // 第?個?協(xié)程
              delay(10)
              println("Second child throws an exception")
              throw ArithmeticException()
          }
      }
      job.join()
      

        這段代碼的輸出如下:

      Second child throws an exception 
      Children are cancelled, but exception is not handled until all children terminate
      The first child finished its non cancellable block CoroutineExceptionHandler got java.lang.ArithmeticException

        

      異常聚合

        當(dāng)協(xié)程的多個?協(xié)程因異常?失敗時,?般規(guī)則是“取第?個異常”,因此將處理第?個異常。在第?個 異常之后發(fā)?的所有其他異常都作為被抑制的異常綁定?第?個異常。

      import kotlinx.coroutines.*
      import java.io.*
      fun main() = runBlocking {
          val handler = CoroutineExceptionHandler { _, exception ->
              println("CoroutineExceptionHandler got $exception with suppressed
                  ${exception.suppressed.contentToString()}")
          }
          val job = GlobalScope.launch(handler) {
              launch {
                  try {
                      delay(Long.MAX_VALUE) // 當(dāng)另?個同級的協(xié)程因 IOException 失敗時,它將被取消
                  } finally {
                      throw ArithmeticException() // 第?個異常
                  }
              }
              launch {
                  delay(100)
                  throw IOException() // ?個異常
              }
              delay(Long.MAX_VALUE)
          }
          job.join()
      }
      

        這段代碼的輸出如下:

      CoroutineExceptionHandler got java.io.IOException with suppressed
      [java.lang.ArithmeticException]
      

        取消異常是透明的,默認(rèn)情況下是未包裝的:

      val handler = CoroutineExceptionHandler { _, exception ->
          println("CoroutineExceptionHandler got $exception")
      }
      val job = GlobalScope.launch(handler) {
          val inner = launch { // 該棧內(nèi)的協(xié)程都將被取消
              launch {
                  launch {
                      throw IOException() // 原始異常
                  }
              }
          }
          try {
              inner.join()
          } catch (e: CancellationException) {
              println("Rethrowing CancellationException with original cause")
              throw e // 取消異常被重新拋出,但原始 IOException 得到了處理
          }
      }
      job.join()
      

        這段代碼的輸出如下:

      Rethrowing CancellationException with original cause
      CoroutineExceptionHandler got java.io.IOException
      

        

      監(jiān)督

        正如我們之前研究的那樣,取消是在協(xié)程的整個層次結(jié)構(gòu)中傳播的雙向關(guān)系。讓我們看?下需要單向取消的情況。

        此類需求的?個良好?例是在其作?域內(nèi)定義作業(yè)的 UI 組件。如果任何?個 UI 的?作業(yè)執(zhí)?失敗了, 它并不總是有必要取消(有效地殺死)整個 UI 組件,但是如果 UI 組件被銷毀了(并且它的作業(yè)也被取消 了),由于它的結(jié)果不再被需要了,它有必要使所有的?作業(yè)執(zhí)?失敗。

        另?個例?是服務(wù)進(jìn)程孵化了?些?作業(yè)并且需要 監(jiān)督 它們的執(zhí)?,追蹤它們的故障并在這些?作業(yè) 執(zhí)?失敗的時候重啟。

       

      監(jiān)督作業(yè)

        SupervisorJob 可以被?于這些?的。它類似于常規(guī)的 Job,唯?的不同是:SupervisorJob 的取消只 會向下傳播。這是?常容易從?例中觀察到的:

      import kotlinx.coroutines.*
      fun main() = runBlocking {
          val supervisor = SupervisorJob()
          with(CoroutineScope(coroutineContext + supervisor)) {
      // 啟動第?個?作業(yè)——這個?例將會忽略它的異常(不要在實(shí)踐中這么做!)
              val firstChild = launch(CoroutineExceptionHandler { _, _ -> }) {
                  println("First child is failing")
                  throw AssertionError("First child is cancelled")
              }
      // 啟動第兩個?作業(yè)
              val secondChild = launch {
                  firstChild.join()
      // 取消了第?個?作業(yè)且沒有傳播給第?個?作業(yè)
                  println("First child is cancelled: ${firstChild.isCancelled}, but second one
                          is still active")
                      try {
                          delay(Long.MAX_VALUE)
                      } finally {
      // 但是取消了監(jiān)督的傳播
                          println("Second child is cancelled because supervisor is cancelled")
                      }
              }
      // 等待直到第?個?作業(yè)失敗且執(zhí)?完成
              firstChild.join()
              println("Cancelling supervisor")
              supervisor.cancel()
              secondChild.join()
          }
      }
      

        這段代碼的輸出如下:

      First child is failing
      First child is cancelled: true, but second one is still active
      Cancelling supervisor
      Second child is cancelled because supervisor is cancelled
      

        

      監(jiān)督作用域

        對于作?域的并發(fā),supervisorScope 可以被?來替代 coroutineScope 來實(shí)現(xiàn)相同的?的。它只會單 向的傳播并且當(dāng)作業(yè)??執(zhí)?失敗的時候?qū)⑺?作業(yè)全部取消。作業(yè)??也會在所有的?作業(yè)執(zhí)? 結(jié)束前等待,就像 coroutineScope 所做的那樣。

      import kotlin.coroutines.*
      import kotlinx.coroutines.*
      fun main() = runBlocking {
          try {
              supervisorScope {
                  val child = launch {
                      try {
                          println("Child is sleeping")
                          delay(Long.MAX_VALUE)
                      } finally {
                          println("Child is cancelled")
                      }
                  }
      // 使? yield 來給我們的?作業(yè)?個機(jī)會來執(zhí)?打印
                  yield()
                  println("Throwing exception from scope")
                  throw AssertionError()
              }
          } catch(e: AssertionError) {
              println("Caught assertion error")
          }
      }
      

        這段代碼的輸出如下:

      Child is sleeping
      Throwing exception from scope
      Child is cancelled
      Caught assertion error
      

        

      監(jiān)督協(xié)程中的異常

        常規(guī)的作業(yè)和監(jiān)督作業(yè)之間的另?個重要區(qū)別是異常處理。監(jiān)督協(xié)程中的每?個?作業(yè)應(yīng)該通過異常 處理機(jī)制處理??的異常。這種差異來?于?作業(yè)的執(zhí)?失敗不會傳播給它的?作業(yè)的事實(shí)。這意味 著在 supervisorScope 內(nèi)部直接啟動的協(xié)程確實(shí)使?了設(shè)置在它們作?域內(nèi)的 CoroutineExceptionHandler,與?協(xié)程的?式相同(查看 CoroutineExceptionHandler ?節(jié)以獲知 更多細(xì)節(jié))。

      import kotlin.coroutines.*
      import kotlinx.coroutines.*
      fun main() = runBlocking {
          val handler = CoroutineExceptionHandler { _, exception ->
              println("CoroutineExceptionHandler got $exception")
          }
          supervisorScope {
              val child = launch(handler) {
                  println("Child throws an exception")
                  throw AssertionError()
              }
              println("Scope is completing")
          }
          println("Scope is completed")
      }
      

        這段代碼的輸出如下:

      Scope is completing
      Child throws an exception
      CoroutineExceptionHandler got java.lang.AssertionError
      Scope is completed
      

        

      posted @ 2021-03-24 13:40  王世楨  閱讀(132)  評論(0)    收藏  舉報
      主站蜘蛛池模板: 日本伊人色综合网| 国产美女久久精品香蕉| 亚洲天堂领先自拍视频网| 樱花草视频www日本韩国| 18禁动漫一区二区三区| 老太脱裤让老头玩ⅹxxxx| 精人妻无码一区二区三区| 17岁日本免费bd完整版观看| 亚洲国产成人不卡高清麻豆| 亚洲美女高潮不断亚洲| 全免费A级毛片免费看无码| 亚洲老熟女一区二区三区 | 亚洲精品久久久中文字幕痴女 | 巨野县| 日本免费人成视频在线观看| 国产精品中文第一字幕| 亚洲精品一区国产精品| 浴室人妻的情欲hd三级国产| 男女xx00上下抽搐动态图| 亚洲区欧美区综合区自拍区| 和艳妇在厨房好爽在线观看| 高清国产一区二区无遮挡| 成年女人碰碰碰视频播放| 亚洲精品国偷自产在线99人热| 尤物国精品午夜福利视频| 无码囯产精品一区二区免费| 少妇高潮喷水在线观看| 日韩av一区二区三区不卡| 亚洲码和欧洲码一二三四| 美女无遮挡免费视频网站| 色综合人人超人人超级国碰| 欧美精品一区二区在线观看播放| 亚洲欧美高清在线精品一区二区| 夜爽8888视频在线观看| 婷婷色婷婷深深爱播五月| 另类专区一区二区三区| 亚洲国产av一区二区| 亚洲一区二区三区18禁| 国内精品自在拍精选| 久久这里只精品国产免费9| 一本一道av无码中文字幕麻豆|