Kotlin Coroutineに入門してみた

はじめに

KotlinのCoroutineを使ってみたく、入門してみました。

やること

KotlinのCoroutineを使うための設定を行い、実際に動かすまでをします。

Coroutineとは

Kotlinの非同期プログラミングをする仕組みのことです。 今回は主にKotlinの公式サイトを参考に実施します。

https://kotlinlang.org/docs/reference/coroutines/coroutines-guide.html

設定

まずは依存関係の設定をします。 ここではGradleを使って設定します。

Gradle設定例

以下のように設定します。(参考

dependencies {
    implementation 'org.jetbrains.kotlinx:kotlinx-coroutines-core:1.3.7'
}
repository {
    jcenter()
}

コードを書く

まずはじめに以下のようなコードを書いてみました。

import kotlinx.coroutines.GlobalScope
import kotlinx.coroutines.launch

fun main(args: Array<String>) {

    GlobalScope.launch {
        println("test1")
    }
    println("test2")
}

このように書くとtest1と出力された後、test2と出力される? というイメージをしましたが実際の出力は以下のようになりました。

test2

test1の出力は??? ここでGlobalScope.launchとはなにかを確認しました。

GlobalScope.launchとは?

バックグラウンドで新しいCoroutineを起動して実行という処理のよう。 公式サイトで説明をみたところ以下のような記述がありました。 結果、メイン処理が終了しているためtest1が出力されなかったということかと。

以下の実験で試します。メイン処理が終了しないように遅延を仕込んでみました。

import kotlinx.coroutines.GlobalScope
import kotlinx.coroutines.delay
import kotlinx.coroutines.launch
import kotlinx.coroutines.runBlocking

fun main(args: Array<String>) {

    GlobalScope.launch {
        println("test1")
    }
    println("test2")

    runBlocking {
        delay(2000L)
    }

}

結果は以下のようになりました。

test1
test2

Coroutineを待つ

先程はdelayさせることでCoroutineの処理を待つことができましたが 待ち合わせする方法が用意されています。

コード例

import kotlinx.coroutines.GlobalScope
import kotlinx.coroutines.launch
import kotlinx.coroutines.runBlocking

fun main(args: Array<String>) {

    runBlocking {

        val job = GlobalScope.launch {
            println("test1")
        }
        println("test2")

        // ここでjobの待ち合わせをする
        job.join()

    }

}

実行結果

test2
test1

動き方のメモ

runBlockingを使うと現在のthreadをブロックする動きとなるよう。 上記の例でrunblockingがないと処理が先に終了してtest1が出力されないという 動きになりました。

他の方法

asyncを使う方法があります。

asyncとは

こちらもCoroutineを作成する処理のようでDeferredを返す処理です。 DeferredはCoroutineの処理が終わった後にその結果が格納されているという動きのようです。

async実装

実装は以下です。

import kotlinx.coroutines.GlobalScope
import kotlinx.coroutines.async

fun main(args: Array<String>) {

    println("before")
    GlobalScope.async {
        println("test")

    }
    println("after")

}

出力結果は以下になります。

before
after
test

上記の実装の場合、何回か実行をした場合に、testが出力される前にプログラムが終了する場合もありました。 よってここでもCoroutineの結果を待つ方法を使うことですべての実行ができるようになります。

awaitを使う

awaitを使うことでCoroutineの結果待ちができます。

awaitを使う実装例
import kotlinx.coroutines.GlobalScope
import kotlinx.coroutines.async
import kotlinx.coroutines.runBlocking

fun main(args: Array<String>) {

    runBlocking {

        println("before")
        GlobalScope.async {
            println("test")
        }.await()
        println("after")

    }

}

出力結果は以下です

before
test
after

まとめ

ここまででCoroutineの機能について触ってみました。 今回はSuspendingについては割愛したので次回こちらに触ってみたいと思います。