我正在启动几个协程,但有Dispatchers.IO.limitedParallelism(1)个调度器,我希望他们一个接一个地执行.

@Test fun `testParallelism`(){
        runBlocking {
            val maxParallel = 1
            val ctx =Dispatchers.IO.limitedParallelism(maxParallel)

            val max = AtomicLong(Long.MIN_VALUE)
            val counter = AtomicLong(0)
            (0..1000).map {
                CoroutineScope(ctx).launch(ctx) {
                    val c = counter.incrementAndGet()
                    max.set(Math.max(max.get(), c))
                    delay(100)
                    counter.decrementAndGet()
                }
            }.joinAll()

            // max is 1000
            assertTrue { max.get() <= maxParallel }
        }

    }

然而,在上面的代码中,断言失败了.看起来所有的协程都是同时启动的.把计数器升到1000.

是不是我在测试代码中做错了什么,或者我对API的理解有误?

推荐答案

你混淆了parallelismconcurrency.你甚至可以互换使用它们,但它们的含义不同.

parallelism是多少协同 routine 可以运行at exactly the same time.concurrency意味着有多少逻辑任务可以run in an overlapping time,所以有多少任务可能已经开始,但在任何时候都还没有完成.

如果我们将并行度设置为1,这意味着一次只能有一个协程在活动执行,但如果它等待任何事情或只是屈服,另一个协程可以跳进来(通过挂起第一个).将并发设置为1意味着协同 routine 将按顺序执行-下一个协同 routine 仅在前一个完成时才开始.

我们使用Dispatcher.limitedParallelism()控制并行性,就像您刚才所做的那样.我们使用MutexSemaphore来控制并发性:

val lock = Mutex()

val max = AtomicLong(Long.MIN_VALUE)
val counter = AtomicLong(0)
(0..1000).map {
    CoroutineScope(Dispatchers.IO).launch {
        lock.withLock {
            val c = counter.incrementAndGet()
            max.set(Math.max(max.get(), c))
            delay(100)
            counter.decrementAndGet()
        }
    }
}.joinAll()

顺便说一句,只要我们像上面那样限制并发性,我们就不需要AtomicLong(也不是易失性)-常规var counter = 0L就可以了.

Kotlin相关问答推荐

在Mapstruct中重用@映射定义

KMP:未能添加cafe.adriel.voyager依赖项

Kotlin - 什么时候和什么时候不喜欢内联函数,为什么?

使用 Kotlin 的 Springboot 中缺少 ResponseEntity 正文属性

第二个协程永远不会执行

使用 Discord4j 交叉发布 Discord 消息

compareBy 如何使用布尔表达式在 kotlin 中工作

Kotlin - 创建指定长度的随机整数的 ArrayList?

使用纯 Kotlin 函数作为 Junit5 方法源

Saripaar formvalidation 在 kotlin 中第二次不起作用

Kotlin:内部类如何访问在外部类中声明为参数的变量?

如何使用 gradle 脚本 Kotlin 构建文件构建可运行的 ShadowJar?

在粘贴时将 java 转换为 kotlin

Kotlin DataBinding 将静态函数传递到布局 xml

使用 Paging 3 时保存并保留 LazyColumn 滚动位置

指定为非null的参数在ArrayAdaper中为null

在kotlin中初始化类变量的正确位置是什么

Kotlin - 具有私有构造函数的类的工厂函数

Kotlin:测试中的 java.lang.NoSuchMethodError

如何在 firebase 数据库中使用 kotlin 协程