问题描述
鉴于我们有一个CompletableFuture f
,在kotlin可挂起的作用域中,我们可以调用f.await()
,我们将挂起直到完成.
Given we have a CompletableFuture f
, in kotlin suspendable scope we can call f.await()
and we will suspend until its done.
我无法使用签名f.await(t)
来实现类似的功能,该功能必须挂起最长t
毫秒,或者如果将来在此期间内完成,则必须更快地返回(以先发生的为准).
I'm having trouble implementing a similar function with signature f.await(t)
which must suspend for maximum t
milliseconds or return sooner if future did complete within that duration (whichever happens first).
这是我尝试过的.
/**
* Suspend current method until future is done or specified duration expires,
* whichever happens first without cancelling the future.
* Returns true if its done, false otherwise.
*/
suspend fun <T> ListenableFuture<T>.await(duration: Long): Boolean {
val future = this
try {
withTimeout(duration) {
withContext(NonCancellable) { // this does not help either
future.await() // i do not expect the future itself to be cancelled
}
}
} catch (t: TimeoutCancellationException) {
// we expected this
} catch (e: Throwable) {
e.printStackTrace()
}
return future.isDone
}
fun main(args: Array<String>) = runBlocking<Unit> {
val future = GlobalScope.future {
try {
repeat(5) {
println("computing")
delay(500)
}
println("complete")
} finally {
withContext(NonCancellable) {
println("cancelling")
delay(500)
println("cancelled")
}
}
}
for (i in 0..10) {
if (future.await(2000)) {
println("checking : done")
} else {
println("checking : not done")
}
}
}
我还需要类似的功能来完成工作.但是也许对此的解决方案也可以帮助我...
I also need a similar function for a job. But maybe solution for this will also help me with that...
此输出为
computing
computing
computing
computing
checking : done
checking : done
checking : done
checking : done
cancelling
checking : done
checking : done
checking : done
checking : done
checking : done
checking : done
checking : done
推荐答案
这是我想到的,我认为这不是一个好的解决方案,因为我很可能会为相当原始的任务创建大量垃圾.
Here is what i came up with, i believe this is not a good solution since, i'm most likely creating a lot of garbage for rather primitive task.
suspend fun <T> CompletableFuture<T>.await(duration: Millis): Boolean {
val timeout = CompletableFuture<Unit>()
GlobalScope.launch {
delay(duration)
timeout.complete(Unit)
}
val anyOfTwo = CompletableFuture.anyOf(this, timeout)
anyOfTwo.await()
return this.isDone
}
fun main() = runBlocking {
val future = CompletableFuture<String>()
GlobalScope.launch {
delay(2000)
println("setting the result (future now ${future.isDone})")
future.complete("something")
}
while (future.isNotDone()) {
println("waiting for the future to complete for the next 500ms")
val isDone = future.await(500)
if (isDone) {
println("future is done")
break
} else {
println("future not done")
}
}
Unit
}
这将给出
waiting for the future to complete for the next 500ms
future not done
waiting for the future to complete for the next 500ms
future not done
waiting for the future to complete for the next 500ms
future not done
waiting for the future to complete for the next 500ms
setting the result (future now false)
future is done
这就是我们想要的...
which is what we wanted...
这篇关于Kotlin协程未来等待超时(不取消)的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!