Kotlinにおける実行上の精密制御



並行性と並列性をサポートするプログラミング言語は、同様にキャンセル機構を提供する必要があります.よく考えられたキャンセルメカニズムもスペースを資源をきれいにします.
このブログ記事では、Cooutineをキャンセルする方法とサスペンド機能の影響を調べます.

基礎
The Job インターフェースと呼ばれるメソッド cancel , これでジョブをキャンセルできます.
fun main() = runBlocking {
  val job = launch {
    repeat(1_00) { i ->
      delay(200)
      println("printing $i")
    }
  }

  delay(1_150)
  job.cancelAndJoin()
  println("cancelled successfully")
}
// printing 0
// printing 1
// printing 2
// printing 3
// printing 4
// cancelled successfully

コールを呼び出すと、ジョブに次の効果があります.
  • 最初のサスペンションポイントで実行ジョブを終了する
  • ジョブがいくつかの子供を持っている場合、彼らはまた、最初の中止点でキャンセルされます
  • ジョブがキャンセルされると、任意の新しいcoroutinesの親として使用することはできません.
  • 置き換えによって最初の仮定を確かめるdelay 呼び出しでThread.sleep
    fun main() = runBlocking {
      val job = launch {
        repeat(1_00) { i ->
          // delay(200)
          Thread.sleep(200)
          println("printing $i")
        }
      }
    
      delay(1_150)
      job.cancelAndJoin()
      println("cancelled successfully")
    }
    // what will be the outcome?
    
    // outcome:
    // printing 0
    // printing ..
    // printing 99
    // cancelled successfully
    
    

    スレッドブロック符号
    一旦遅延関数仕事を取り除いたならば、仕事は停止点を持たないので、それは計算の終わりまで働き続けます.Thread.sleep スレッドブロック関数は、リバースコードブロックを中断関数に抽出します.
    fun main() = runBlocking {
        val job = launch {
            repeat(1_00) { i -> threadBlockingFn(i) }
            println("job completed")
        }
        delay(1_150)
        job.cancelAndJoin()
        println("cancelled successfully")
    }
    
    suspend fun threadBlockingFn(i: Int) = coroutineScope {
        Thread.sleep(200)
        println("printing $i")
    }
    
    fun println(msg: Any) = with(Thread.currentThread()) {
        kotlin.io.println("$id:$name\t=> $msg")
    } 
    // what will be the outcome?
    
    // outcome:
    // 1:main   => printing 0
    // 1:main   => printing .. 🧐
    // 1:main   => printing 99 🤔
    // 1:main   => job completed
    // 1:main   => cancelled successfully
    
    
    job シングルスレッドで動作しており、関数も中断していますthreadBlockingFn main スレッドは解除要求を監視するためにunblockされません.では、この場合のサスペンションポイントの作成方法は?
    より細かい制御をするためには、threadBlockFn そして、親の仕事でそれに加わってください
    fun main() = runBlocking {
        val job = launch {
            repeat(1_00) { i -> launch { threadBlockingFn(i) }.join() }
            // also produces same output
            // repeat(1_00) { i -> async { threadBlockingFn(i) }.await() }
            println("job completed")
        }
        delay(1_150)
        job.cancelAndJoin()
        println("cancelled successfully")
    }
    // output: 
    // 1:main   => printing 0
    // 1:main   => printing 1
    // 1:main   => printing 2
    // 1:main   => printing 3
    // 1:main   => printing 4
    // 1:main   => printing 5
    // 1:main   => cancelled successfully
    
    
    デフォルトのディスパッチャをデリゲートthreadBlockFn 実行
    fun main() = runBlocking {
        val job = launch {
            repeat(1_00) { i -> withContext(Dispatchers.Default) { threadBlockingFn(i) } }
            println("job completed")
        }
        delay(1_150)
        job.cancelAndJoin()
        println("cancelled successfully")
    }
    // output: 
    // 14:DefaultDispatcher-worker-1    => printing 0
    // 14:DefaultDispatcher-worker-1    => printing 1
    // 14:DefaultDispatcher-worker-1    => printing 2
    // 14:DefaultDispatcher-worker-1    => printing 3
    // 14:DefaultDispatcher-worker-1    => printing 4
    // 14:DefaultDispatcher-worker-1    => printing 5
    // 1:main   => cancelled successfully
    
    

    概要
    Cooutineは、中断された関数と一緒にディスパッチャは、コードブロックの実行を完全に制御する非常に強力なメカニズムを提供します.デフォルトの関数delay はキャンセル注意関数です.要約すると、細かい規則を達成するために、親指規則の後の使用を言います
  • コードベースのサスペンションポイントをもっと
  • スレッドブロックコード領域を避ける
  • Coroutinesは非常に軽量です
  • 用途async/await , withContext 周辺空間
  • ブレークダウン計算の重い演算子をより多くのサスペンションポイントと小さな部分に

  • 派遣者
    Coroutineは、Docで言及されるように利用できるディスパッチャの異なる種類を持っています
    • Dispatchers.Default — is used by all standard builders if no dispatcher or any other ContinuationInterceptor is specified in their context. It uses a common pool of shared background threads. This is an appropriate choice for compute-intensive coroutines that consume CPU resources.
    • Dispatchers.IO — uses a shared pool of on-demand created threads and is designed for offloading of IO-intensive blocking operations (like file I/O and blocking socket I/O).
    • Dispatchers.Unconfined — starts coroutine execution in the current call-frame until the first suspension, whereupon the coroutine builder function returns. The coroutine will later resume in whatever thread used by the corresponding suspending function, without confining it to any specific thread or pool. The Unconfined dispatcher should not normally be used in code.
    • Private thread pools can be created with newSingleThreadContext and newFixedThreadPoolContext.
    • An arbitrary Executor can be converted to a dispatcher with the asCoroutineDispatcher extension function.