我们有一个特殊的用例,如果我们可以用Kotlin的协程来解决我们的问题,或者我们必须依赖CompletableFutures,我需要帮助才能找到答案 .
基本上,我们为单线程本身的服务器编写插件 . 这意味着,我们可以使用不同的钩子来添加逻辑,这个逻辑总是在主线程中运行,不能被阻塞 . 另外,在使用服务器的API时,我们必须在主线程内,因为给定的方法不是线程安全的 .
为了使用异步代码,我们've used the server'的调度程序产生一个 生产环境 者/消费者系统,它在后台运行异步任务并将结果同步回服务器's main thread. The implementation shouldn'这很重要,所以这里只是一个例子在实践中看起来像:
// 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);
}
几天前我问了一个关于async / await的类似问题,这导致了一个看起来像这样的解决方案:
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更好地编写和处理 .
谢谢
1 回答
试试
withContext
功能 . 将代码包装在其中,它将在所需的上下文中执行 .例如:
您可以使用您选择的CoroutinesContext替换
Dispatchers.Main
注意:
withContext
函数是"suspending"函数,它必须仅在Coroutine Scope
中执行