157
126

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 5 years have passed since last update.

【Kotlin】Coroutineを理解する

Last updated at Posted at 2018-09-30

#はじめに
Kotlin 1.1からCoroutineが実験的に組み込まれました。
Coroutineとは**「特定のスレッドに束縛されない、中断可能な計算インスタンス」**です。
非同期処理で用いられますが、Threadよりも軽量で、実行途中で処理を中断・再開することができます。

#準備
Coroutineを利用するために、build.gradleに下記の情報を追記します。
今回は2018/09/30時点での最新版(0.30.0)を使用しています。
更新状況はここから確認できます。

build.gradle
dependencies {
    ...
    implementation "org.jetbrains.kotlinx:kotlinx-coroutines-core:0.30.0"
}
build.gradle
kotlin {
    experimental {
        coroutines 'enable'
    }
}
build.gradle
repositories {
    jcenter()
}

#使い方
Coroutineの作成にはCoroutineビルダーを使用します。
##runBlocking
現在のスレッドをブロックするビルダーです。任意の型を返します。

runBlocking {
    // 何かしらの処理
}

###Sample

fun main(args:Array<String>) {
    println(1)
    runBlocking {
        println(2)
    }
    println(3)
}

/**
 * 実行結果
 * 1
 * 2
 * 3
 */

##launch

戻り値としてJobを返すビルダーです。

0.26.1からlaunchGlobalScope.launchになりました。

GlobalScope.launch {
    // 何かしらの処理 
}

###Sample
現在のスレッドをブロックしないため、launch内の処理が実行される前にプログラムが終了します。

fun main(args:Array<String>) {
    println(1)
    launch {
        println(2)
    }
    println(3)
}

/**
 * 実行結果
 * 1
 * 3
 */

引数で実行するスレッドを指定できます。
引数なしの場合はDispatchers.Defaultが設定されます。

0.26.1からCommonPoolDispatchers.Defaultになりました。
0.26.1からUIDispatchers.Unconfinedになりました。

/**
 * Dispatchers.Default -> バックグラウンドスレッド
 * Dispatchers.Unconfined -> メインスレッド
 */
GlobalScope.launch(Dispatchers.Unconfined) {
    // 何かしらの処理 
}

Job#join()を利用すれば、呼び出し先のcoroutineの終了まで呼び出し元のcoroutineを中断できます。

runBlocking {
    GlobalScope.launch() {
        // 何かしらの処理 
    }.join()
}

###Sample

fun main(args:Array<String>) = runBlocking {
    println(1)
    GlobalScope.launch {
        println(2)
    }.join()
    println(3)
}

/**
 * 実行結果
 * 1
 * 2
 * 3
 */

##async
戻り値としてDeferred<T>を返すビルダーです。
Coroutineの処理が終わったタイミングで戻り値を取得できます。

0.26.1からasyncGlobalScope.asyncになりました。

GlobalScope.async {
    // 何かしらの処理 
}

###Sample
launch同様、現在のスレッドをブロックしないため、async内の処理が実行されません。

fun main(args:Array<String>) {
    println(1)
    GlobalScope.async {
        println(2)
    }
    println(3)
}

/**
 * 実行結果
 * 1
 * 3
 */

Job#join()同様、Deferred<T>#await()を利用すれば、呼び出し先のCoroutineの終了まで呼び出し元のCoroutineを中断できます。

runBlocking {
    GlobalScope.async {
        // 何かしらの処理 
    }.await()
}

###Sample

fun main(args:Array<String>) = runBlocking {
    println(1)
    GlobalScope.async {
        println(2)
    }.await()
    println(3)
}

/**
 * 実行結果
 * 1
 * 2
 * 3
 */

#Suspend関数
Coroutineを中断できる関数です。suspendをつけることで宣言できます。
CoroutineかSuspend関数内からのみ実行できます。

suspend fun sampleSuspending(){
     // 何かしらの処理       
}

###Sample
delayはSuspend関数なので実行できます。

fun main(args:Array<String>) = runBlocking {
    println(1)
    sampleSuspending()
    println(3)
}

suspend fun sampleSuspending() {
    delay(1000)
    println(2) 
}

/**
 * 実行結果
 * 1
 * (1秒中断)
 * 2
 * 3
 */ 

#まとめ
非同期処理を直感的に理解しやすく、とても簡潔に記述できるようになりました。

#参考
[Coroutines - Kotlin Programming Language]
(https://kotlinlang.org/docs/reference/coroutines.html)
[AndroidでKotlin Coroutinesを使ってみる]
(http://tech.furyu.jp/blog/?p=6388)
[eaglesakuraの技術ブログ]
(https://eaglesakura.hatenablog.com/entry/2018/09/21/142152)
[Kotlin の Coroutine を概観する]
(https://qiita.com/kawmra/items/ee4acb7db61f70dec9a8)
[入門Kotlin coroutines]
(https://qiita.com/k-kagurazaka@github/items/8595ca60a5c8d31bbe37)

157
126
3

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
157
126

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?