遍历Kotlin Channel时跳过偶数元素问题排查
Kotlin Channels 迭代丢失偶数元素问题
问题代码
class TestChannels { @Test fun testChannels() { runBlocking { val someNumbers = Channel<Int>(UNLIMITED) repeat(100) { someNumbers.send(it) } someNumbers.close() for (number in someNumbers) { println(number) } } } }
预期输出
1 2 3 4 5 6 7 8 9 10
实际输出
1 3 5 7 9
版本差异
- Kotlin 1.7.21:使用
LinkedListChannel实现UNLIMITED通道,代码运行正常,无元素丢失 - Kotlin 1.8.22:使用
BufferedChannel实现UNLIMITED通道,出现偶数元素丢失的异常情况
解决方案
该问题是Kotlin 1.8.x版本中BufferedChannel的迭代器实现bug导致的,可通过以下方式规避:
改用
consumeEach消费通道consumeEach是Kotlin协程通道推荐的消费方式,能正确读取所有元素:runBlocking { val someNumbers = Channel<Int>(UNLIMITED) repeat(100) { someNumbers.send(it) } someNumbers.close() someNumbers.consumeEach { println(it) } }使用
receiveCatching循环读取
通过手动循环调用receiveCatching直到通道关闭,确保所有元素被读取:runBlocking { val someNumbers = Channel<Int>(UNLIMITED) repeat(100) { someNumbers.send(it) } someNumbers.close() while (true) { val result = someNumbers.receiveCatching() if (result.isFailure) break println(result.getOrNull()) } }降级到Kotlin 1.7.21
暂时回退到无问题的版本,等待官方修复该bug。
内容的提问来源于stack exchange,提问作者Kirill Moskvin
相关产品推荐
相关产品推荐

