takeWhileInclusive 的这种实现安全吗?

2023-12-07

我发现以下包容性的实现takeWhile (found here)

fun <T> Sequence<T>.takeWhileInclusive(pred: (T) -> Boolean): Sequence<T> {
    var shouldContinue = true
    return takeWhile {
        val result = shouldContinue
        shouldContinue = pred(it)
        result
    }
}

问题是我不是 100% 相信如果在并行序列.

我担心的是我们会依赖shouldContinue变量来知道何时停止,但我们没有同步它的访问。

有什么见解吗?


这是我到目前为止所想到的。

问题澄清

问题不清楚。没有这样的东西并行序列我可能把它们搞混了Java并行流。我的意思是一个序列同时消耗.

序列是同步的

正如 @LouisWasserman 在评论中指出的那样,序列并不是为并行执行而设计的。特别是SequenceBuilder注释为@RestrictSuspension。引用自Kotlin 协程 repo:

这意味着在其范围内 lambda 的任何 SequenceBuilder 扩展都不能调用 suspendContinuation 或其他通用挂起函数

话虽如此,正如 @MarkoTopolnik 评论的那样,它们仍然可以像任何其他对象一样在并行程序中使用。

并行使用的序列

作为示例,这是并行使用序列的第一次尝试

fun launchProcessor(id: Int, iterator: Iterator<Int>) = launch {
    println("[${Thread.currentThread().name}] Processor #$id received ${iterator.next()}")
}

fun main(args: Array<String>) {
    val s = sequenceOf(0, 1, 2, 3, 4, 5, 6, 7, 8, 9)
    runBlocking {
        val iterator = s.iterator()
        repeat(10) { launchProcessor(it, iterator) }
    }
}

此代码打印:

[ForkJoinPool.commonPool-worker-2] 处理器 #1 收到 1

[ForkJoinPool.commonPool-worker-1] 处理器 #0 收到 0

[ForkJoinPool.commonPool-worker-3] 处理器 #2 收到 2

[ForkJoinPool.commonPool-worker-2] 处理器 #3 收到 3

[ForkJoinPool.commonPool-worker-1] 处理器 #4 收到 3

[ForkJoinPool.commonPool-worker-3] 处理器 #5 收到 3

[ForkJoinPool.commonPool-worker-1] 处理器 #7 收到 5

[ForkJoinPool.commonPool-worker-2] 处理器 #6 收到 4

[ForkJoinPool.commonPool-worker-1] 处理器 #9 收到 7

[ForkJoinPool.commonPool-worker-3] 处理器 #8 收到 6

哪个当然是不是我们想要的。因为有些数字会被消耗两次。

进入频道

另一方面,如果我们要使用通道,我们可以编写如下内容:

fun produceNumbers() = produce {
    var x = 1 // start from 1
    while (true) {
        send(x++) // produce next
        delay(100) // wait 0.1s
    }
}

fun launchProcessor(id: Int, channel: ReceiveChannel<Int>) = launch {
    channel.consumeEach {
        println("[${Thread.currentThread().name}] Processor #$id received $it")
    }
}

fun main(args: Array<String>) = runBlocking<Unit> {
    val producer = produceNumbers()
    repeat(5) { launchProcessor(it, producer) }
    delay(1000)
    producer.cancel() // cancel producer coroutine and thus kill them all
}

那么输出是:

[ForkJoinPool.commonPool-worker-2] 处理器 #0 收到 1

[ForkJoinPool.commonPool-worker-2] 处理器 #0 收到 2

[ForkJoinPool.commonPool-worker-1] 处理器 #1 收到 3

[ForkJoinPool.commonPool-worker-2] 处理器 #2 收到 4

[ForkJoinPool.commonPool-worker-1] 处理器 #3 收到 5

[ForkJoinPool.commonPool-worker-2] 处理器 #4 收到 6

[ForkJoinPool.commonPool-worker-2] 处理器 #0 收到 7

[ForkJoinPool.commonPool-worker-1] 处理器 #1 收到 8

[ForkJoinPool.commonPool-worker-1] 处理器 #2 收到 9

[ForkJoinPool.commonPool-worker-2] 处理器 #3 收到 10

此外,我们可以实施takeWhileInclusive像这样的频道方法:

fun <E> ReceiveChannel<E>.takeWhileInclusive(
        context: CoroutineContext = Unconfined,
        predicate: suspend (E) -> Boolean
): ReceiveChannel<E> = produce(context) {
    var shouldContinue = true
    consumeEach {
        val currentShouldContinue = shouldContinue
        shouldContinue = predicate(it)
        if (!currentShouldContinue) return@produce
        send(it)
    }
}

它按预期工作。

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

takeWhileInclusive 的这种实现安全吗? 的相关文章

  • 在 Kotlin 中以编程方式更改区域设置

    我有一些在 Java 中以编程方式更改语言环境的代码 但是当我的应用程序迁移到 Kotlin 时 我无法再更改区域设置 例如 Java 中的这段代码运行得非常好 public static final void setAppLocale S
  • oracle日期序列?

    我有一个 oracle 数据库 我需要一个包含 2 年所有日期的表 例如来自01 01 2011 to 01 01 2013 首先我想到了一个序列 但显然唯一支持的类型是数字 所以现在我正在寻找一种有效的方法来做到这一点 欢呼骗局 如果您想
  • Kotlin:覆盖子类型中的通用属性

    我试图编写一些通用代码 但无法摆脱Type of PROPERTY is not a subtype of the overridden property error 我的代码的简化版本 abstract class BaseP
  • 从 DecorView@2da7146[MyActivity] 中找不到 ViewTreeLifecycleOwner

    从撰写更新后alpha 11 to alpha 12 or beta 01 每当我打开具有撰写视图的活动或片段时 我都会遇到此崩溃 我在用AppCompatActivity它实现了LifecycleOwner 所以这非常奇怪 java la
  • 在多模块项目中访问绑定适配器

    我有一个多模块项目 其中应用程序模块包含我的绑定适配器 而我的功能模块取决于我的应用程序模块 因为它是动态功能模块 应用程序 包含绑定适配器 gt 动态功能模块 存在布局的地方 我在所有模块中启用了数据绑定和 kapt 我无法成功构建应用程
  • 为什么线程比协程表现出更好的性能?

    我编写了 3 个简单的程序来测试协程相对于线程的性能优势 每个程序都会执行许多常见的简单计算 所有程序都彼此分开运行 除了执行时间之外 我还通过以下方式测量了 CPU 使用率Visual VMIDE 插件 第一个程序使用以下方法进行所有计算
  • 在Android中绘制圆角矩形

    我已经发现这个问题 https stackoverflow com questions 5618402 how to draw rounded rectangle in android ui解决方案是这段代码
  • 在 Kotlin 中创建 Spring 的 ParameterizedTypeReference 实例

    我正在尝试学习 Kotlin 并测试它如何与 Spring Boot 配合使用 我的应用程序使用 mongo 数据库来存储数据 并且我有用于检索数据的 Jersey 资源 我正在使用它进行测试spring boot test and Res
  • 错误:链接引用失败。 -> 排队作业

    我正在使用 Kotlin 学习 Android Material Design 一切都很顺利 直到我尝试使用 android support design widget FloatingActionButton 当我重建项目时 我收到以下错
  • 在viewpager2中禁用动画

    我有 viewpager2 和扩展 FragmentStateAdapter 的适配器 我希望用户仅通过单击选项卡布局即可转到另一个页面 我已禁用此 viewpager2 的用户输入 但是当我单击选项卡时 有页面之间快速滑动的动画 但我只想
  • 如何使用 Google 的 GithubBrowserSample 方法在片段之间共享视图模型?

    我对 Android 架构组件的使用非常陌生 因此我决定使用 GithubBrowserSample 来构建我的应用程序来实现我的许多用例 但我有一个问题 我不知道使用这种方法在片段之间共享视图模型的正确方法是什么 我想共享视图模型 因为我
  • Android计算两个日期之间的天数

    我编写了以下代码来查找两个日期之间的天数 startDateValue new Date startDate endDateValue new Date endDate long diff endDateValue getTime star
  • 为什么我们在 Kotlin 中使用“伴生对象”来替代 Java 静态字段?

    伴生对象 的本意是什么 到目前为止我一直用它来代替Java的static当我需要它的时候 我很困惑 为什么叫 同伴 呢 这是否意味着要创建多个static属性 我必须将其分组在里面companion object block 为了立即创建一
  • 来自java的kotlin函数默认参数

    给出以下 Kotlin 类 class Foo public fun bar i Int 0 Int 2 i 我应该如何在没有 java groovy 代码中的任何参数的情况下调用 bar 函数 def f new Foo f bar th
  • 如何使 FirebaseAuth.AuthStateListener 在 Kotlin 中工作?

    class LoginActivity AppCompatActivity private val firebaseAuth FirebaseAuth getInstance private val firebaseAuthListener
  • Jetpack Compose 中复选框中的透明复选标记

    在我的 Compose 应用程序中 我需要创建一个圆形复选框 我已经通过下面的代码实现了这一点 Composable fun CircleCheckBox isChecked Boolean modifier Modifier Modifi
  • Android Room 数据库 - 未解析的引用 @Entity 和其他注释

    我在我的应用程序中使用 Android Room Persistence 库 v 1 0 0 alpha1 虽然它工作正常 但当我在 Android studio 中打开模型类 Kotlin 数据类 时 它显示用于 Room 数据库的所有注
  • 让协程等待之前的调用

    我还没有完全掌握 Kotlin 协程 基本上我希望协程在执行之前等待任何先前的调用完成 下面的代码似乎可以工作 但它正在做我认为它正在做的事情吗 private var saveJob Job null fun save saveJob s
  • 我收到“循环依赖”Android Dagger Hilt 错误

    我从头开始检查了所有内容 但找不到错误 我找不到错误 可能是什么 我收到以下编译错误 HomeViewModel java 6 error ComponentProcessor MiscError dagger internal codeg
  • 如何运行 Kotlin REPL kotlinc-jvm 或 kotlinc

    我对 Kotlin 完全陌生 我正在尝试运行 Kotlin REPL 下列的this https kotlinlang org docs tutorials command line html running the repl 考虑到我使用

随机推荐