首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >共享懒惰协同执行/回忆性协同执行

共享懒惰协同执行/回忆性协同执行
EN

Stack Overflow用户
提问于 2022-05-17 06:10:56
回答 1查看 124关注 0票数 0

上下文:

代码语言:javascript
复制
import kotlinx.coroutines.CoroutineStart
import kotlinx.coroutines.async
import kotlinx.coroutines.coroutineScope

data class DatabaseData(
    val a: String,
    val b: String
)

interface DatabaseFetcher {
    suspend fun get(): DatabaseData
}

class MyClass(
    private val databaseFetcher: DatabaseFetcher
) {
    suspend fun a() = coroutineScope {
        val a = async { databaseFetcher.get().a }
        //imagine more async{}'s here
        a //imagine a gets computed in regards to the other async{}'s as well
    }

    suspend fun b() = databaseFetcher.get().b
}

class MyController(private val databaseFetcher: DatabaseFetcher) {
    suspend fun someFun() = coroutineScope {
        // the reduced example doesn't need a coroutineScope of course, imagine some async{} here
        MyClass(databaseFetcher)
    }
}

如果a()b()MyClass上被调用,我只尝试调用MyClass一次。从根本上说,这是一个懒散的未来,在调用a()b()时就开始了,但需要协同。

到目前为止,我已经尝试过:

  • 在这里不能使用by lazy{}作为coroutineScope问题,我也不能使用withContext(Dispatchers.IO),因为我使用自定义上下文(多线程、Spring请求作用域数据等)--在这里传递上下文似乎有些麻烦(这会不会是一种糟糕的做法?)在构造MyClass时,
  • 无法传递,因为如果D16永远不会被await()>ed>ed> on,则会无限期阻塞,这可能发生在既不调用a()或D19时。它也无限期地阻塞,因为在构造coroutineScope时会构造相应的MyClass,这将在MyClass完全构建之后调用为a()和b(),因为(据我所知)只有在完成了所有的子程序时,coroutineScope才会被解除阻塞,对于在curent作用域
  • 之外等待的懒惰异步,使用更广泛的coroutine上下文可能会泄漏,而这是真的吗?我找不到很多关于

的事

这是在GraphQL上下文中完成的,其中可以选择a、b或两者。对于这一点,有一些简单的解决方案,但由于我仍然在学习协同机制,我想知道是否有一个优雅的解决方案,我还没有看到。CoroutineStart.LAZY的问题真的让我大吃一惊:)

EN

回答 1

Stack Overflow用户

回答已采纳

发布于 2022-05-20 22:41:48

我已经找到了解决办法:

代码语言:javascript
复制
fun <T : () -> U, U> T.memoized(): suspend () -> Deferred<U> {
    val self = this
    val deferred: CompletableDeferred<U> = CompletableDeferred()
    val started = AtomicBoolean(false)
    return suspend {
        if (started.compareAndExchange(false, true)) {
            deferred
        } else {
            coroutineScope {
                async {
                    deferred.complete(self())
                    deferred.await()
                }
            }
        }
    }
}

任何() -> T函数(基本上是任何带有捕获参数的函数)都可以是.memoized()。无论被调用者首先调用什么,返回的suspend fun都将用于启动Deferred<U>,同时允许所述被调用者在他认为合适的时候阻塞:

代码语言:javascript
复制
val expensive = { someExpensiveFun(param, param2 }.memoize();
withContext(Dispatchers.IO) { // or some other context
    val a = expensive()
    val b = expensive()

    a.await()
    b.await()
}
票数 0
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/72268944

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档