我们有一个特殊的用例,如果我们可以用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);
}
几天前我问了一个关于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更好地编写和处理。
谢谢
尝试withContext
功能。将代码包装在其中,它将在所需的上下文中执行。
例如:
withContext(Dispatchers.Main) {
//This will run in Main Thread
}
您可以使用您选择的Coroutines Context替换Dispatchers.Main
注意:withContext
函数是“暂停”函数,它必须只在Coroutine Scope
中执行
立即执行
如果您确实需要立即执行该怎么办?为此,您可以使用
Dispatchers.Main.immediate
当协程已经在正确的上下文中时立即执行协同程序
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
launch(Dispatchers.Main.immediate) {
log("A")
}
log("B")
}
打印
OUTPUT:
// A
// B