代码之家  ›  专栏  ›  技术社区  ›  guenhter

Kotlin与超时的协同路由

  •  9
  • guenhter  · 技术社区  · 7 年前

    我目前正在编写一个测试函数,它应该运行一个块或(当达到某个超时时)抛出一个异常。

    我试过了 Coroutines 在科特林,但最终的结果是 协同程序 CompletableFuture :

    fun <T> runBlockWithTimeout(maxTimeout: Long, block: () -> T ): T {
        val future = CompletableFuture<T>()
    
        // runs the coroutine
        launch { block() }
    
        return future.get(maxTimeout, TimeUnit.MILLISECONDS)
    }
    

    这是可行的,但我不确定这是否是解决kotlin问题的预期方法。

    我还尝试了其他方法:

    runBlocking {
        withTimeout(maxTimeout) {
            block()
        }
    }
    

    但这似乎并不像 block 呼叫,例如。 Thread.sleep(...)

    这也是 可完成的未来 走近路还是有更好的路?

    更新1 我想要实现的目标:

    var rabbitResults: List = ... // are filled async via RabbitListeners
    ...
    waitMax(1000).toSucceed {
        assertThat(rabbitResults).hasSize(1)
    }
    waitMax(1000).toSucceed {
        assertThat(nextQueue).hasSize(3)
    }
    ...
    
    1 回复  |  直到 6 年前
        1
  •  37
  •   Roman Elizarov    7 年前

    withTimeout { ... } 旨在 取消 超时时正在进行的操作,只有在有问题的操作是 可取消 .

    它起作用的原因 future.get(timeout, unit) 是因为它只是 等待 超时。它实际上不会以任何方式取消或中止在超时后仍继续执行的后台操作。

    如果你想在协同程序中模仿类似的行为,那么你应该 等待 超时,如下所示:

    val d = async { block() } // run the block code in background
    withTimeout(timeout, unit) { d.await() } // wait with timeout
    

    它工作正常,因为 await 是一个可取消的函数,您可以通过读取 its API documentation .

    然而,如果您想在超时时实际取消正在进行的操作,那么您应该以异步和可取消的方式实现代码。取消是 合作的 因此,首先,您在代码中使用的底层库必须提供支持取消正在进行的操作的异步API。

    有关取消和超时的更多信息,请参阅 coroutines guide 看KotlinConf的 Deep Dive into Coroutines 关于如何将协同路由与异步库集成。