[Kotlin Coルーチン]可ルーチン(1)CoルーチンBasics


Coルーチン公式ドキュメント翻訳器-1 CoルーチンBasics
  • 以下の文書はKotlinLangが提供するCoules公式文書の翻訳(意訳):
  • 翻訳を最小限に抑え、Reader-Fiendlyを作成します.
  • コルディン、頭上の空き地
    以下に示すコードはIntelliJまたはKotlin Playgroundで実行されます.
    import kotlinx.coroutines.*
    
    fun main() {
        GlobalScope.launch { // launch a new coroutine in background and continue
            delay(1000L) // non-blocking delay for 1 second (default time unit is ms)
            println("World!") // print after delay
        }
        println("Hello,") // main thread continues while coroutine is delayed
        Thread.sleep(2000L) // block main thread for 2 seconds to keep JVM alive
    }
    コードを実行すると、次の結果が得られます.
    Hello,
    World!
    どうしてこんな結果になったの?サブプログラムは軽量化ねじです.CoroutineScopeという名前のContextでは、LaunchなどのKoroutine BuilderでKoroutineをインストールできます.
    上のコードはGlobalScopeというコンテキストにコードルーチンがインストールされています.これは、「このコード・インスタンスのライフサイクルは、アプリケーションのライフサイクル全体に依存します」ことを意味します.
    GlobalScope.Launch関数とdelay関数は、以前に使用したスレッド関数(thread{})とsleep関数(Thread.sleep()にそれぞれ置き換えることができます.では、以下のコードは正常に動作しますか?
    import kotlin.concurrent.thread
    import kotlinx.coroutines.*
    
    fun main() {
        thread { 
            delay(1000L) 
            println("World!") 
        }
        println("Hello,") 
        Thread.sleep(2000L) 
    }
    あ….残念ながらそうはいかないdelay関数はsuspend関数として定義されるため、スレッドはブロックされません.ただし、delay関数自体がcoutineを停止するため、delayはcoutine内部で使用する必要があります.
    では、コーラ定でスレッドを完全に阻止することはできませんか?
    上記の例はsuspend関数delayとthreadのネストです.sleep関数が混在しています.これにより、コードを記述することは、スレッドをブロックする部分を特定することが困難になります.したがって、coluceneはrunblockcoluceneコンストラクタを代替案として使用することを提案し、coluceneを使用してスレッドをブロックすることができる.
    import kotlinx.coroutines.*
    
    fun main() { 
        GlobalScope.launch { 
            delay(1000L)
            println("World!")
        }
        println("Hello,") 
        runBlocking {     // 이 코루틴 빌더가 스레드를 블락합니다.
            delay(2000L)  
        } 
    }
    結果は以下の通りですが、今回作成したコードは上記のコードとは異なり、スレッドを区別しない関数のみが使用されます.runblockingは、内部関数が終了するまでメインスレッドをブロックします.上記のコードはmain関数全体を囲む形でrunblockingを記述することもできます.
    import kotlinx.coroutines.*
    
    fun main() = runBlocking<Unit> { 
        GlobalScope.launch { 
            delay(1000L)
            println("World!")
        }
        println("Hello,") 
        runBlocking {     // 이 코루틴 빌더가 스레드를 블락합니다.
            delay(2000L)  
        } 
    }
    新しく作成されたメソッドではrunblockingはUnit(cottlinではmain関数がUnit,ほほほ)を返すトップクラスのcoutineになります.この方法は、デバイステストのsuspend関数を作成するためにも使用できます.
    class MyTest {
        @Test
        fun testMySuspendingFunction() = runBlocking<Unit> {
            // suspend 함수를 여기서 테스트 합니다.
        }
    }
    しかし、必ずメインスレッドの起動を止めなければなりませんか?
    別のcoutine作業中に遅延するのはよくありません.今回は、新しい方法でスレッドを起動します.
    import kotlinx.coroutines.*
    
    fun main() = runBlocking {
        val job = GlobalScope.launch { // 코루틴을 launch 하면 job 객체가 이를 참조합니다.
            delay(1000L)
            println("World!")
        }
        println("Hello,")
        job.join() // 코루틴의 작업이 끝날때까지 기다립니다.   
    }
    Jobオブジェクトはlaunch関数の戻りタイプです.したがって、プライマリ・コード・インスタンスは、バックグラウンド・ジョブ(runblockingによって構築されたコード・インスタンス)を遅延させる必要はありません.
    こうぞうどうき
    今までGlobalScopeでしたlaunchを使用してトップクラスのcolucene(アプリケーション全体で生き残るcolucene)を作成することを学びました.どんなに軽量であっても、これらのスレッドはプログラムの実行中にメモリリソースを使用し続け、これらのスレッドオブジェクトへの参照を失うとメモリ占有が発生します.では、これらのコルドオブジェクトのすべての参照はコルディンを使用するべきですか?これはコルディンを用いた典型的な防図案である.
    構造同期という非常に驚くべき方法を使用することができます.GlobalScopeでcoutineを起動するよりも、実行する特定の範囲内でcoutineを構築できます.
    次の例では、メイン関数はrunblockcoルーチンを使用します.すべてのcoutineビルダー(runblockingもcoutineビルダー)は、固有のコードブロックに別のcoutineScopeを追加することができます.この方法を使用すると、joinを明示的に使用することなくcoutineを起動できます.このようにして、親スレッドは内部スレッドが完了するまで終了できないからです.
    import kotlinx.coroutines.*
    
    fun main() = runBlocking { // this: CoroutineScope
        launch { 
            delay(1000L)
            println("World!")
        }
        println("Hello,")
    }
    ホッチキス
    コルディンscopeは別のコンストラクタを提供しています.Scopeでは、CoroutineScopeビルダーを宣言して別のScopeを作成できます.すべてのサブスレッドが終了するまで終了しないスレッドスキャンを作成できます.
    これらの点から、runblockingとcoroutineScopeは似ているように見えますが、両者の違いは、他の操作を行うとrunblockingが現在のスレッドをブロックし、coroutineScopeが現在のスレッドを待つことです.これらの違いによりcoroutineScopeはsuspend関数でありrunBlockingは通常関数である.
    import kotlinx.coroutines.*
    
    fun main() = runBlocking { // this: CoroutineScope
        launch { 
            delay(200L)
            println("Task from runBlocking")
        }
        
        coroutineScope { // Creates a coroutine scope
            launch {
                delay(500L) 
                println("Task from nested launch")
            }
        
            delay(100L)
            println("Task from coroutine scope") // This line will be printed before the nested launch
        }
        
        println("Coroutine scope is over") // This line is not printed until the nested launch completes
    }
    Task from coroutine scope
    Task from runBlocking
    Task from nested launch
    Coroutine scope is over
    再構築:suspend関数の作成
    launchのコードを分離したい場合は、どのように再パッケージすればいいですか?コルディン内部の関数を除外するにはsuspend modifierを使用する必要があります.suspend関数は、通常の関数のようにcoutineで使用してもよいし、delayなどの他のsuspend関数を使用してもよい.
    import kotlinx.coroutines.*
    
    fun main() = runBlocking {
        launch { doWorld() }
        println("Hello,")
    }
    
    suspend fun doWorld() {
        delay(1000L)
        println("World!")
    }
    Hello,
    World!
    機能分離関数にmain関数のscopeで発生するscopeが含まれている場合、どうすればいいですか?この場合、機能をCoroutineScopeの拡張関数に分割することで機能分離を実現したい場合がありますが、コードの作成が不十分な可能性があります.
    最も理想的な解決策は、この関数を含むCoroutineScopeをクラスの変数として使用するか、クラス内で関数を継承して実装することです.CoroutineScope(CoroutineContext)を使用することもできますが、この機能を実行すると、開発者が自己制御できなくなるため、構造的に不安定になる可能性があるので使用しないほうがいいです.
    コルディンは本当に楽です.
    次の2つのコードを実行しましょう.
    import kotlinx.coroutines.*
    
    fun main() = runBlocking {
        repeat(100_000) { // launch a lot of coroutines
            launch {
                delay(5000L)
                print(".")
            }
        }
    }
    import kotlin.concurrent.thread
    
    fun main() {
        thread { 
            repeat(100_000) { // launch a lot of coroutines
                Thread.sleep(5000L)
                print(".")
        }
    }
    10万個のcoutineを同時に実行すると、各coutineは正常にポイント操作を実行できます.ただし、スレッドで実行すると、中間に出力メモリが表示され、プロセスが終了します.
    グローバルスレッドはDaemon Threadと同じです
    次のコードを実行
    import kotlinx.coroutines.*
    
    fun main() = runBlocking {
        GlobalScope.launch {
            repeat(1000) { i ->
                println("I'm sleeping $i ...")
                delay(500L)
            }
        }
        delay(1300L) // just quit after delay    
    }
    I'm sleeping 0 ...
    I'm sleeping 1 ...
    I'm sleeping 2 ...
    グローバルScopeから開始されたスレッドは、プロセスのライフサイクルを保護しません.つまり、グローバルScopeで実行されるすべての操作は、プロセスの実行時に正常に動作することは保証されません.ThreadとDaemon Threadのように
    テキスト
  • https://kotlinlang.org/docs/basics.html