短需求:具有创建上下文的能力,该上下文将仅在单个线程中执行(例如,没有并行性)。
附加要求:最好使用现有的CommonPool (例如线程池)来执行这些任务
实际上,kotlin有newSingleThreadContext方法,它将创建单独的线程,并将所有任务调度到其中。但是,这是专门的线程,所以~1000这样的上下文将需要大量的资源。
因此,我希望具有以下特征的上下文:
发布于 2021-12-27 20:43:11
从1.6.0版本的kotlinx.coroutines库开始,我们可以在CoroutineDispatcher对象上使用limitedParallelism函数,它允许您在不创建额外线程池的情况下限制并行性,并提供了一种为无绑定并行创建调度程序的统一方法。
使用示例:
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条协同执行。
它应该解决这个问题:
最大一项任务可以同时执行。
发布于 2019-12-04 02:39:30
这里有一个解决方案:
例如,当您说withSerialContext(Dispatchers.Default) {doWork()}时,它在默认的dispatcher线程上执行doWork(),但是它的所有部分都会像在runBlocking{}中那样一次执行一个。请注意,即使每次都是一个线程,也不能保证整个操作都是同一个线程。
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)
}
}
}发布于 2018-08-31 11:40:17
我发现,没有简单的解决方案来创建这样的上下文。
关于githuib https://github.com/Kotlin/kotlinx.coroutines/issues/261还有一个悬而未决的问题。
我想当我找到正确的解决方案时,我会更新这个问题。
https://stackoverflow.com/questions/50355071
复制相似问题