コルーチンの基本
コルーチンとは
About Coroutines
Kotlinの非同期関数。 スレッドと違い、何千個作成してもCPUの負荷を増大させない
最初のコルーチン
Coroutineは、CoroutinScope内部で実行し、CoroutineScopeは、実行されたCoroutineが全て完了するまで、自身を終了させない。
// kotlinxをインポートする import kotlinx.coroutines.* fun main() = runBlocking { // this: CoroutineScope launch { // Coroutineの生成 (async) delay(5000L) // サスペンド関数 (await) println("World") } println("Hello") } /* 出力 Hello World */
runBlocking
: CoroutineScopeの生成関数launch
: Coroutineの生成関数。CoroutineScopeに属するメソッドdelay()
: サスペンド関数。コルーチンを停止するが、カレントスレッドをブロックしない。await
にあたる
サスペンド関数の生成
サスペンド関数
Suspending functions can be used inside coroutines just like regular functions, but their additional feature is that they can, in turn, > use other suspending functions (like delay in this example) to suspend execution of a coroutine.
コルーチンの実行を中断する。つまりサスペンド関数自体が、await
に相当する。
suspend
修飾子をつける。また内部でサスペンド関数を呼ぶことができる。
suspend fun doWorld() { delay(5000L) // 内部でサスペンド関数を呼ぶことができる println("World") } fun main = runBlocking { // this: CoroutineScope launch { doWorld() } println("Hello") } /* Hello World */
スコープビルダー
CoroutinScopeの生成は以下がある。
coroutineScope{}
は、サスペンド関数なので、runBlocking{}
で一旦スコープを生成する必要がある。
coroutineScope使用例
import kotlinx.coroutines.* fun main() { runBlocking { doWorld() // サスペンド関数 (await) println("runBlocking end") } println("main end") } suspend fun doWorld() = coroutineScope { // this: CoroutineScope launch { delay(1000L) println("World") } println("Hello") } /* 出力結果 Hello World runBlocking end main end */
スコープの生成と並列性
coroutineScope {}
は内部に複数の並列処理を実行するためのサスペンド関数を含めることができる。
import kotlinx.coroutines.* fun main() = runBlocking { doWorld() // サスペンド関数 (await) println("Done") } suspend fun doWorld() = coroutineScope { // this: CoroutineScope launch { // async delay(2000L) // await println("World 2") } launch { // async delay(1000L) // await println("World 1") } println("Hello") } /* Hello World 1 World 2 Done */
明示的なjob
An explicit job
launch
コルーチンビルダーは、Job
オブジェクトを返すので、それを使って、コルーチンの完了を明示的に待機させることができる。
job object
: 起動されたコルーチンに対するハンドル
例として、子供のコルーチンの完了を待機させる
// CoroutineScope内部 val job = launch { // async delay(1000L) // await println("World") } println("Hello") job.join() // 子供のコルーチンが完了するまで待機する println("Done") /* Hello World Done */
コルーチンは軽量である
スレッドと違い、コルーチンを何千個生成してもCPUの負荷に影響を与えない。
import kotlinx.coroutines.* fun main() = runBlocking { repeat(100_000) { // launch a lot of coroutines launch { delay(5000L) print(".") } } }