2 回答

TA貢獻1875條經驗 獲得超5個贊
我寫了一些測試代碼:
fun main(args: Array<String>) = runBlocking {
val future = calculateAsync()
val result = future.await(2000)
println("result=$result")
}
suspend fun <T> CompletableFuture<T>.await(duration: Long): T? {
val future = this
var result: T? = null
try {
withTimeout(duration) {
result = future.await()
}
} catch (t: TimeoutCancellationException) {
println("timeout exception")
} catch (e: Throwable) {
e.printStackTrace()
}
return result
}
@Throws(InterruptedException::class)
fun calculateAsync(): CompletableFuture<String> {
val completableFuture = CompletableFuture<String>()
Executors.newCachedThreadPool().submit {
Thread.sleep(3000)
println("after sleep")
completableFuture.complete("Completed")
}
return completableFuture
}
運行此代碼后,我們將得到一個輸出:
timeout exception
result=null
after sleep
我們看到我們的擴展函數await返回null,因為我們將超時設置為 2000 毫秒,但CompletableFuture在 3000 毫秒后完成。在這種情況下CompletableFuture被取消(它的isCancelled屬性返回true),但我們在calculateAsync函數中運行的線程繼續執行(我們在日志中看到它after sleep)。
如果我們future.await(4000)在main函數中將超時持續時間設置為 4000 毫秒,我們將看到下一個輸出:
after sleep
result=Completed
現在我們有了一些結果,因為CompletableFuture執行速度超過 4000 毫秒。

TA貢獻2051條經驗 獲得超10個贊
這是我想出的,我認為這不是一個好的解決方案,因為我很可能會為相當原始的任務創造很多垃圾。
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
這就是我們想要的...
添加回答
舉報