首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >如何在Kotlin中的公共池中创建单线程协同上下文?

如何在Kotlin中的公共池中创建单线程协同上下文?
EN

Stack Overflow用户
提问于 2018-05-15 16:25:29
回答 3查看 2.5K关注 0票数 2

短需求:具有创建上下文的能力,该上下文将仅在单个线程中执行(例如,没有并行性)。

附加要求:最好使用现有的CommonPool (例如线程池)来执行这些任务

实际上,kotlin有newSingleThreadContext方法,它将创建单独的线程,并将所有任务调度到其中。但是,这是专门的线程,所以~1000这样的上下文将需要大量的资源。

因此,我希望具有以下特征的上下文:

  • 最大一项任务可以同时执行
  • 此上下文应该重用任何其他上下文(例如父上下文)。例如,上下文不应包含额外的线程
EN

回答 3

Stack Overflow用户

回答已采纳

发布于 2021-12-27 20:43:11

1.6.0版本的kotlinx.coroutines库开始,我们可以在CoroutineDispatcher对象上使用limitedParallelism函数,它允许您在不创建额外线程池的情况下限制并行性,并提供了一种为无绑定并行创建调度程序的统一方法。

使用示例:

代码语言:javascript
复制
class UserRepository {
    private val dbDispatcher = Dispatchers.IO.limitedParallelism(1)

    suspend fun getUserById(userId: Int): User? = withContext(dbDispatcher) {
        executeQuery("SELECT * FROM users WHERE id = $1", userId).singleOrNull()
   }
}

limitedParallelism(1)保证并行性限制--最多可在此调度程序中并发执行1条协同执行。

它应该解决这个问题:

最大一项任务可以同时执行。

票数 4
EN

Stack Overflow用户

发布于 2019-12-04 02:39:30

这里有一个解决方案:

例如,当您说withSerialContext(Dispatchers.Default) {doWork()}时,它在默认的dispatcher线程上执行doWork(),但是它的所有部分都会像在runBlocking{}中那样一次执行一个。请注意,即使每次都是一个线程,也不能保证整个操作都是同一个线程。

代码语言:javascript
复制
suspend fun <T> withSerialContext(
        context: CoroutineDispatcher,
        block: suspend CoroutineScope.() -> T
): T = withContext(SerialContextDispatcher(context), block)

private class SerialContextDispatcher(private val target: CoroutineDispatcher) : CoroutineDispatcher() {

    private val q = ConcurrentLinkedQueue<Runnable>()
    //Whoever CASes this false->true schedules execution of runproc
    private val pending = AtomicBoolean(false)
    //Only one of these runs at a time
    private val runproc = object: Runnable {
        override fun run() {
            while(true) {
                val proc = q.poll();
                if (proc != null) {
                    try {
                        proc.run()
                    }
                    catch (e: Throwable) {
                        target.dispatch(EmptyCoroutineContext, this)
                        throw e
                    }
                } else {
                    pending.set(false);
                    if (q.isEmpty() || !pending.compareAndSet(false, true)) {
                        return
                    }
                }
            }
        }
    }

    override fun dispatch(context: CoroutineContext, block: Runnable) {
        q.add(block)
        if (pending.compareAndSet(false, true)) {
            target.dispatch(EmptyCoroutineContext, runproc)
        }
    }
}
票数 2
EN

Stack Overflow用户

发布于 2018-08-31 11:40:17

我发现,没有简单的解决方案来创建这样的上下文。

关于githuib https://github.com/Kotlin/kotlinx.coroutines/issues/261还有一个悬而未决的问题。

我想当我找到正确的解决方案时,我会更新这个问题。

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

https://stackoverflow.com/questions/50355071

复制
相关文章

相似问题

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