繁体   English   中英

Kotlin Worker Pool - 长时间运行的 Kotlin 协程和 Java 堆 OutOfMemory

[英]Kotlin Worker Pool - Long Running Kotlin Coroutine and Java Heap OutOfMemory

我正在尝试在 Kotlin 中复制一个工作池: https ://gobyexample.com/worker-pools

它工作得很好,但我的问题是我得到 OutOfMemoryError 因为只要协程正在运行,来自工作协程的所有对象引用都保存在堆中。 我怎样才能避免这个问题?

这是我的代码:

我在服务 A 中创建一个通道,并在每次收到通道对象时接收数据。

class ServiceA(
) {

    val channel = Channel<Pair<String,ByteArray>>(10000)

    private val coroutineScope = CoroutineScope(SupervisorJob() + Dispatchers.Default)

    @PostConstruct
    fun createWorkerGroup(){
        coroutineScope.launch{
            for(x in 1..5){
                launch {
                    println("Create Worker $x")
                    while (true){
                            uploadImage(channel.receive() )
                    }
                }
            }
        }
    }
 private suspend fun uploadImage(urlAndImage: Pair<String, ByteArray>){
            val (url,image) = urlAndImage
            println("Uploading Image: $url")

    }

在我的控制器方法中,我将数据发送到通道:

uploadService.channel.send(Pair(url, image.bytes))

工作池可以由协程范围使用适当的调度程序自动处理。

如果图像上传执行阻塞操作,您可能需要使用 IO 调度程序,如下所示: CoroutineScope(Dispatchers.IO.limitedParallelism(5)) 我省略了SupervisorJob ,因为您不需要它用于将在createWorkerGroup()中创建的父协程,而是用于它创建的父协程。 不要忘记创建不再需要时取消CoroutineScope的逻辑。

之后,您可以在没有性能开销的情况下随意启动协程,就像您之前所做的那样:

@PostConstruct
fun createWorkerGroup() {
    coroutineScope.launch{
        supervisorScope {
            channel.consumeEach {
                launch {
                    uploadImage(it)
                }
            }
        }
    }
}

这是创建和使用工作池的正确方法,但您需要对其进行测试以查看它是否消除了OutOfMemoryError 您可能还想尝试减少通道的容量。 祝你好运!

谢谢@Halex 的帮助,这是我的 Kotlin 协程工作池,带有适当的垃圾收集

private val coroutineScope = CoroutineScope(Dispatchers.Default)
@OptIn(ExperimentalCoroutinesApi::class)
private val superVisorScope = CoroutineScope(SupervisorJob() + Dispatchers.IO.limitedParallelism(5))
@PostConstruct
fun createWorkerGroup() {
    coroutineScope.launch {
        superVisorScope.launch {
            channel.consumeEach {
                launch {
                    uploadImage(it)
                }
            }
        }
    }
    coroutineScope.cancel()
}

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM