Что означает потребление канала Kotlin?

Документы Kotlin используют термин consume как для описания поведения таких методов, как Channel#first(), так и в именах таких методов, как Channel#consumeEach().

Мне трудно понять, что означает использование канала по сравнению с неиспользованием.

Как вообще выглядит непотребление?

Предоставляет ли Channel API доступ к элементам в канале без потребления?

Кроме consumeEach(), всегда ли потребление подразумевает полное опустошение канала?


person Julian A.    schedule 19.11.2018    source источник


Ответы (2)


Использование «consume» означает, что это терминальное действие, что ничто за пределами этой команды не может прочитать из канала. Вы можете увидеть это яснее в документации по API для first и consumeEach:

Операция терминальная. Эта функция использует все элементы исходного ReceiveChannel.

Обратите внимание, что в документах также есть предупреждения о том, что этот API изменится в будущем.

Прочтите KT-167, чтобы получить полезные комментарии по этой теме.

person Jayson Minard    schedule 19.11.2018

Вывод следующего кода иллюстрирует значение «потребления» и эффект consumeEach.

fun f1() = runBlocking {
    val numbers = produce {
        repeat(5) {
            send(it)
            delay(100)
        }
    }
    run {
        for (i in numbers) {
            trace(i)
            if (i == 2) return@run
        }
    }
    trace("after run")
    for (i in numbers) {
        trace(i)
    }
    trace("exiting f1")
}
f1()

println()

fun f2() = runBlocking {
    val numbers = produce {
        repeat(5) {
            send(it)
            delay(100)
        }
    }
    run {
        numbers.consumeEach {
            trace(it)
            if (it == 2) return@run
        }
    }
    trace("after run")
    for (i in numbers) {
        trace(i)
    }
    trace("exiting f2")
}
f2()

Выход:

[main @coroutine#1]: 0
[main @coroutine#1]: 1
[main @coroutine#1]: 2
[main @coroutine#1]: after run
[main @coroutine#1]: 3
[main @coroutine#1]: 4
[main @coroutine#1]: exiting f1

[main @coroutine#3]: 0
[main @coroutine#3]: 1
[main @coroutine#3]: 2
[main @coroutine#3]: after run
[main @coroutine#3]: exiting f2

Мы видим, что (в f1) мы можем остановить итерацию по каналу, а затем продолжить с того места, на котором остановились. Однако при использовании consumeEach (в f2) мы не можем остановиться и продолжить, даже несмотря на то, что изначально канал был способен выдавать числа больше 2.

person Julian A.    schedule 11.12.2018