如何在 Kotlin 中创建一个可调度函数,可以在延迟间隔内调度多次,但在间隔结束时运行一次?

问题描述 投票:0回答:0

如何创建一个可以多次调用的函数从非暂停上下文并且在自第一次调用以来的特定延迟之后,可暂停函数运行?

我试图在 Kotlin 中重新创建的 Javascript 代码:

const DELAY_MS = 500

const sleep = (ms) => new Promise((resolve) => setTimeout(resolve, ms))
const schedulable = () => console.log('schedulable function is running')
let timeout = null

const schedule = () => {
  if (!timeout) {
    timeout = setTimeout(() => {
      timeout = null
      schedulable()
    }, DELAY_MS)
  }
}

;(async () => {
  schedule()
  await sleep(100)
  schedule()
  schedule()
  await sleep(200)
  schedule()
})()

// result: 'schedulable function is running' is printed once

Kotlin 尝试(似乎可行,但使用了 GlobalScope):


object SchedulableAttempt {
  private fun schedulable() {
    println("schedulable function is running")
  }

  private const val DELAY_MS = 500L
  private var deferred: Deferred<Unit>? = null

  fun schedule() {
    if(deferred === null){
      synchronized(this){
        deferred = GlobalScope.async {
          delay(DELAY_MS)
          deferred = null
          schedulable()
        }
      }
    }
  }
}

fun main() {
  thread {
    SchedulableAttempt.schedule()
    Thread.sleep(100)
    SchedulableAttempt.schedule()
    SchedulableAttempt.schedule()
    Thread.sleep(200)
    SchedulableAttempt.schedule()
  }

  runBlocking { // just to keep the app running
    delay(1000)
  }
}

如何在 Kotlin 中正确执行此操作?这样的解决方案有什么陷阱吗? Kotlin 文档明确表示要避免在非顶级协程的情况下使用 GlobalScope,因为它会造成内存泄漏

javascript kotlin asynchronous kotlin-coroutines
© www.soinside.com 2019 - 2024. All rights reserved.