我试图了解哪个是在Kotlin中以预定速率触发异步作业的最佳方法,而应用程序通常正在运行它的正常任务。假设我有一个简单的应用程序,每秒只打印出“......”,但是每5秒我想要另一个作业/线程/协同程序(它们最适合)打印“你有消息!”。对于异步工作,我有一个类NotificationProducer
,它看起来像这样。
class NotificationProducer {
fun produce() {
println("You have a message!")
}
}
然后,我的主要方法看起来像这样。
while (true) {
println("...")
sleep(1000)
}
我应该使用GlobalScope.async
,Timer().schedule(...)
或一些Quartz工作来实现我想要的吗?任何建议都非常感谢。关键是通知必须来自另一个类(例如NotificationProducer)
如果我正确理解了这个问题,使用Kotlin协程可以实现如下:
class Presenter : CoroutineScope { // implement CoroutineScope to create local scope
private var job: Job = Job()
override val coroutineContext: CoroutineContext
get() = Dispatchers.Default + job
// this method will help to stop execution of a coroutine.
// Call it to cancel coroutine and to break the while loop defined in the coroutine below
fun cancel() {
job.cancel()
}
fun schedule() = launch { // launching the coroutine
var seconds = 1
val producer = NotificationProducer()
while (true) {
println("...")
delay(1000)
if (seconds++ == 5) {
producer.produce()
seconds = 1
}
}
}
}
然后你可以使用Presenter
类的一个实例启动协程并停止它:
val presenter = Presenter()
presenter.schedule() // calling `schedule()` function launches the coroutine
//...
presenter.cancel() // cancel the coroutine when you need
对于简单的调度要求,我使用协同程序实现它,因为它很有趣:
class NotificationProducerScheduler(val service: NotificationProducer, val interval: Long, val initialDelay: Long?) :
CoroutineScope {
private val job = Job()
private val singleThreadExecutor = Executors.newSingleThreadExecutor()
override val coroutineContext: CoroutineContext
get() = job + singleThreadExecutor.asCoroutineDispatcher()
fun stop() {
job.cancel()
singleThreadExecutor.shutdown()
}
fun start() = launch {
initialDelay?.let {
delay(it)
}
while (isActive) {
service.produce()
delay(interval)
}
println("coroutine done")
}
}
否则,Java并发API也非常可靠:
class NotificationProducerSchedulerJavaScheduler(
val service: NotificationProducer,
val interval: Long,
val initialDelay: Long = 0
) {
private val scheduler = Executors.newScheduledThreadPool(1)
private val task = Runnable { service.produce() }
fun stop() {
scheduler.shutdown()
}
fun start() {
scheduler.scheduleWithFixedDelay(task, initialDelay, interval, TimeUnit.MILLISECONDS)
}
}