我们有一个特殊的用例,我需要帮助找出是否可以解决Kotlin协程的问题,或者是否必须依赖CompletableFutures。
基本上,我们为单线程本身的服务器编写插件。这意味着,我们可以使用不同的钩子来添加逻辑,并且该逻辑始终在主线程中运行,并且必须禁止该主线程。此外,在使用服务器的API时,由于给定的方法不是线程安全的,因此我们必须位于主线程中。
为使此代码与异步代码一起使用,我们使用服务器的调度程序生成了一个生产者/消费者系统,该系统在后台运行异步任务,并将结果同步回到服务器的主线程。实现的重要性不那么重要,因此,这里仅是一个示例,说明实际情况:
// execute hook that runs when a user on the server runs a command
override fun execute(sender: CommandSender, args: Array<out String>) {
// call comes from the main thread
db.fetchBalance(sender.name)
// fetchBalance runs asynchronous code without blocking
// the current thread by utilizing a consumer/producer system
.thenAccept {
// the CompletableFuture is resolved after completion
// here we are in the main thread again, so that we can access
// server methods in a thread safe manner
sender.sendMessage("Your balance: $it")
}
}
现在我的问题是,是否可以将Kotlin代码替换为上面的示例,使其更具可读性,例如JavaScript中的async / await。要记住,在JavaScript中我们可以这样做:
async function onBalanceRequest(client, name) {
let balance = await db.fetchBalance(name);
client.sendMessage("Your money: " + balance);
}
几天前,我曾问过一个关于异步/等待的类似问题,这导致了一个看起来像这样的解决方案:
private fun onBalanceRequest(sender: CommandSender) {
// call comes from the main thread
GlobalScope.launch {
// here we are within a new thread
val money = db.fetchBalance(sender.name).join()
// here we are within the same thread, which is
// not the main thread, so the code below isn't safe
sender.sendMessage("Your balance: $money")
}
}
如评论中所述,问题在于,在“等待未来”之后,代码在协程的线程中运行。所以我的问题是,是否可以实现像协程描述的那样,或者是否不是针对本用例而设计的。我已经读过为衍生的协程指定线程的可能性,但是此线程将被阻塞,因此将无法正常工作。
如果CompletableFutures是解决此问题的唯一方法,我们将坚持使用它们,但我想尝试一下协程,因为它们看起来比CompletableFutures更好地编写和处理。
谢谢
答案 0 :(得分:1)
尝试使用withContext
函数。将您的代码包装在其中,它将在所需的上下文中执行。
例如:
withContext(Dispatchers.Main) {
//This will run in Main Thread
}
您可以将Dispatchers.Main
替换为您选择的CoroutinesContext
注意:withContext
函数是“挂起”函数,必须仅在Coroutine Scope
答案 1 :(得分:0)
立即执行
如果确实需要立即执行怎么办?为此,您可以使用
Dispatchers.Main.immediate
在正确的上下文中立即执行协程
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
launch(Dispatchers.Main.immediate) {
log("A")
}
log("B")
}
打印
OUTPUT:
// A
// B