亚洲在线久爱草,狠狠天天香蕉网,天天搞日日干久草,伊人亚洲日本欧美

為了賬號安全,請及時綁定郵箱和手機立即綁定
已解決430363個問題,去搜搜看,總會有你想問的

Kotlin 協程未來等待超時(無取消)

Kotlin 協程未來等待超時(無取消)

汪汪一只貓 2022-05-21 20:46:50
鑒于我們有一個CompletableFuture f, 在 kotlin 可掛起的范圍內,我們可以調用f.await()并且我們將掛起直到它完成。我在實現一個帶有簽名的類似函數時遇到了麻煩,如果未來在該持續時間內完成(以先發生者為準),該簽名f.await(t)必須暫停最大毫秒或更快返回。t這是我嘗試過的。/** * 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")      }   }}我還需要一個類似的功能來完成工作。但也許這個解決方案也會幫助我......輸出為computingcomputingcomputingcomputingchecking : donechecking : donechecking : donechecking : donecancellingchecking : donechecking : donechecking : donechecking : donechecking : donechecking : donechecking : done
查看完整描述

2 回答

?
慕田峪4524236

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 毫秒。


查看完整回答
反對 回復 2022-05-21
?
侃侃無極

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

這就是我們想要的...


查看完整回答
反對 回復 2022-05-21
  • 2 回答
  • 0 關注
  • 397 瀏覽
慕課專欄
更多

添加回答

舉報

0/150
提交
取消
微信客服

購課補貼
聯系客服咨詢優惠詳情

幫助反饋 APP下載

慕課網APP
您的移動學習伙伴

公眾號

掃描二維碼
關注慕課網微信公眾號