我想在Kotlin中实现Dead man's switch。这样做是在收到最后一个TIME_INTERVAL
后MyEvent
秒发出通知。收到新的MyEvent
后,它会重新启动计时器。
private val stopWatch = object : () -> Unit {
var timer = System.currentTimeMillis()
var isRunning = false
override fun invoke() {
timer = System.currentTimeMillis()
if (isRunning) return
synchronized(this) {
isRunning = true
while (System.currentTimeMillis() - timer <= TIME_INTERVAL) {}
fireNotification()
isRunning = false
}
}
}
override fun onSomeEvent(e: MyEvent?) {
runAsync(stopWatch)
}
使用kotlin.concurrent
或Java标准库是否有更简单或更简单的方法来获得此功能?
答案 0 :(得分:1)
如果我理解正确的话,你的代码就是在时间间隔过去之前循环什么都不做。这是一个坏主意,因为它消耗了大量CPU无所事事,而不仅仅是等待。
我会使用ScheduledExecutr来安排通知的触发。在通知被解雇之前,我会取消返回的未来:
import java.time.Instant.now
import java.util.concurrent.Executors
import java.util.concurrent.ScheduledFuture
import java.util.concurrent.TimeUnit
class StopWatch {
private var future: ScheduledFuture<Void>? = null;
private val executor = Executors.newSingleThreadScheduledExecutor()
fun onSomeEvent() {
synchronized(this) {
future.let {
future?.cancel(false)
future = null
}
val command = {
synchronized(this@StopWatch) {
future = null
}
fireNotification()
null
}
future = executor.schedule(command, 2, TimeUnit.SECONDS)
}
println("${now()} - event")
}
private fun fireNotification() {
println("${now()} - notification")
}
fun shutdown() {
executor.shutdown()
}
}
fun main(args: Array<String>) {
val stopWatch = StopWatch()
stopWatch.onSomeEvent()
Thread.sleep(1000)
stopWatch.onSomeEvent()
Thread.sleep(1000)
stopWatch.onSomeEvent()
Thread.sleep(1000)
stopWatch.onSomeEvent()
Thread.sleep(3000)
stopWatch.onSomeEvent()
stopWatch.shutdown()
}
打印哪些:
2017-05-07T12:45:55.647Z - event
2017-05-07T12:45:56.741Z - event
2017-05-07T12:45:57.743Z - event
2017-05-07T12:45:58.745Z - event
2017-05-07T12:46:00.747Z - notification
2017-05-07T12:46:01.750Z - event
2017-05-07T12:46:03.753Z - notification