Я написал некоторый тестовый код:
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
), но функция Thread, которую мы запустили в calculateAsync
, продолжает выполняться (мы видим это в журналах after sleep
).
Если мы установим длительность тайм-аута в 4000 миллисекунд future.await(4000)
в функции main
, мы увидим следующий результат:
after sleep
result=Completed
Теперь у нас есть некоторый результат, потому что CompletableFuture
выполняется быстрее, чем 4000 миллисекунд.