0
1

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 1 year has passed since last update.

Kotlin Coroutine 整理1編

Posted at

はじめに

Kotlinを学習する中で、新しく学んだことを整理いたします。

ルーチンとコルーチンの違い

  • ルーチンは一度開始すると、終了するまで止まりません。

  • ルーチンは一度終了すると、ルーチン内の情報が消えてしまいます。

  • コルーチンは中断され、再開することが可能です。

  • 中断されても、ルーチン内の情報は消えません。


package coroutine

import kotlinx.coroutines.*

suspend fun newRoutine(){ // 他のsuspend関数を呼び出すことができます。
    val num1 = 1
    val num2 = 2
    yield() // スレッドを譲ります。中断と再開。
    printWithThread("${num1 + num2}") // ルーチンが中断された後、メモリ上に保存されて再開されます。
}

fun main(): Unit = runBlocking { // コルーチンの世界へ接続します。
    printWithThread("START")
    launch { // 戻り値のないコルーチンを作成します。
        newRoutine() // すぐには実行されません。
    }
    yield() // newRoutineで譲渡され、ENDが呼び出されます。
    printWithThread("END")
}

fun printWithThread(str: Any){
    println("[${Thread.currentThread().name}] $str")
}

結果

runBlockingを実行して1番目のコルーチンを実行し、launchで2番目のコルーチンを実行します。しかし、yieldの宣言により途中でメモリに保存された状態で再開されます。

[main @coroutine#1] START
[main @coroutine#1] END
[main @coroutine#2] 3

プロセス、スレッド、そしてコルーチン

スレッドはプロセスに従属しています。スレッドがプロセスを変更することはできません。
コルーチンのコードが実行されるためには、スレッドが必要です。
中断後に再開される際には、別のスレッドに割り当てられることがあります。

コルーチンのコードはどのスレッドでも実行できます。

プロセスは独立したメモリを持ち、コンテキストスイッチング時にはすべてのデータが変更されます。

スレッドはヒープエリアを共有し、スタックエリアだけが置き換えられます。

コルーチンが同じスレッドで実行される場合、コンテキストスイッチングが異なります。
メモリの置き換えは発生しません。 -> 並行性

コルーチンは自らの位置を譲ることができます。非プリエンプティブ

runBlocking

新しいコルーチンを作成し、ルーチンとコルーチンを接続します。
スレッドをブロッキングします。


fun main() { // コルーチンの世界へ接続します。
    runBlocking {
        printWithThread("START")
        launch {
            delay(2_000L) // yield
            printWithThread("LAUNCH END")
        }
    }
    printWithThread("END")
}

結果

[main @coroutine#1] START
[main @coroutine#2] LAUNCH END
[main] END

launch

戻り値のないコードを実行します。
Jobオブジェクトを返すことができます。

start

fun main(): Unit = runBlocking { // コルーチンの世界へ接続します。
    val job = launch(start = CoroutineStart.LAZY) {
        printWithThread("Hello launch")
    }

    delay(1000)
    job.start()
}

cancel

fun main(): Unit = runBlocking { // コルーチンの世界へ接続します。
    val job = launch {
        (1..5).forEach{
            printWithThread(it)
            delay(300)
        }
    }

    delay(1000)
    job.cancel()
}
[main @coroutine#2] 1
[main @coroutine#2] 2
[main @coroutine#2] 3
[main @coroutine#2] 4

join

awaitに似ています。

fun main(): Unit = runBlocking { // コルーチンの世界へ接続します。
    val job1 = launch {
        delay(1000)
        printWithThread("job 1")
    }
    job1.join()
    val job2 = launch {
        delay(1000)
        printWithThread("job 2")
    }
    job2.start()
}

async

結果を返すことができます。Promiseのようなものです。
複数のAPIを一度に呼び出すことができます。


fun main(): Unit = runBlocking { // コルーチンの世界へ接続します。
    val job1 = async {
        3 + 5
    }
    val eight = job1.await()
    print(eight)
}


fun main(): Unit = runBlocking { // コルーチンの世界へ接続します。
    val time = measureTimeMillis {
        val job2 = async { apiCall2() }
        val job1 = async { apiCall1() }
        printWithThread(job1.await() + job2.await())
    }
    printWithThread("所要時間: $time ms")
}

/*
fun main(): Unit = runBlocking { // コルーチンの世界へ接続します。
    val job1 = async { apiCall1() }
    val job2 = async { apiCall2(job1.await()) }
    
}

suspend fun apiCall1(): Int{
    delay(1000L)
    return 1
}

suspend fun apiCall2(num : Int): Int{
    delay(1000L)
    return 2 + num
}
*/

suspend fun apiCall1(): Int{
    delay(1000L)
    return 1
}

suspend fun apiCall2(): Int{
    delay(1000L)
    return 2
}

/*
[main @coroutine#1] 3
[main @coroutine#1] 所要時間: 1065 ms
*/

Coroutine.LAZY

CoroutineStart.LAZYは、実際にコルーチンの実行が完了するまで待機するため、時間がかかります。

    val job2 = async(start= CoroutineStart.LAZY) { apiCall2() }
0
1
0

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
0
1

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?