kotlin - 将数据从回调推送到 Kotlin 协程的方法是什么

标签 kotlin kotlinx.coroutines

假设我想在 DownloadQueue 中使用缓存像例子。
协程的乐趣在于可以在单线程算法中使用简单的数据结构(例如 HashMap)。

但是我想使用有限的缓存,并将额外的条目驱逐到较慢的持久存储中。
例如,我可以取 Guava + CacheBuilder + RemovalListener : https://github.com/google/guava/wiki/CachesExplained#removal-listeners

这里有一个问题:RemovalListener是一个非挂起的回调,所以无法将数据推送到 Channels或来自回调的任何内容。

// This is placed in a suspend context (e.g. within `actor`)
val cache = CacheBuilder.newBuilder().maximumSize(1000)
    .expireAfterWrite(10, TimeUnit.SECONDS)
    .removalListener<Key, Value> { n ->
        expireChannel.sendBlocking(n.value!!) // <-- could sendBlocking be used here???
    }.build<Key, Value>()

据我了解,runBlocking阻塞当前线程的执行,因此它阻塞当前协程,并且它将无法接收/处理数据。

有没有办法制作RemovalListener -like 回调协程友好?

我可以想象使用由 RemovalListener 填充的无界队列的解决方法。而有问题的协程最终会检查队列。

最佳答案

不阻塞删除监听器(从而破坏缓存)的唯一方法是拥有一个缓冲 channel 。这意味着两个变化:

  • 创建 SendChannel具有非零容量,请参阅 Channel(capacity) 考虑不同的行为。这主要取决于如果超过消费者可以处理的元素过期,应该采取什么行为。
  • 使用SendChannel.offer()而不是 SendChannel.sendBlocking() .如果返回 false您可以实现备份行为,例如记录故障,以便找出内存和丢失事件之间的最佳平衡点。
  • 关于kotlin - 将数据从回调推送到 Kotlin 协程的方法是什么,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/53263690/

    相关文章:

    kotlin - 如何指定默认子命令?

    android - 在 Gradle 属性文件中将您的 API_KEY 添加到从 GitHub 下载的 Android 项目

    android - 如何获取对象内部的上下文?

    Android camera2 createCaptureRequest 获取YUV_420_888图像时返回全黑像素

    kotlin GlobalScope,runBlocking 在 kotlin.coroutines 中不可用。*

    android - mpAndroidChart java.lang.NegativeArraySizeException : -46 for Kotlin

    android - PrintManager.print() 并更改了 attachBaseContext 中的语言环境

    不阻塞调用者的 Kotlin async/await 语法

    kotlin - 应使用 CoroutineScope 的扩展函数或挂起函数

    android - android.os.Looper 中的方法 myLooper 未使用协程模拟