我试图了解哪种方法是在Kotlin中按计划的速率启动异步作业的最佳方法,而应用程序通常正在运行它的正常任务。假设我有一个简单的应用程序,该应用程序每秒仅打印“ ...”,但是每5秒我要另一个作业/线程/协程(最适合)打印“您有消息!”。对于异步作业,我有一个NotificationProducer
类,它看起来像这样。
class NotificationProducer {
fun produce() {
println("You have a message!")
}
}
然后,我的主要方法如下。
while (true) {
println("...")
sleep(1000)
}
我应该使用GlobalScope.async
,Timer().schedule(...)
还是某些Quartz作业来实现我想要的?任何建议都将受到高度赞赏。关键是通知必须来自另一个类(例如NotificationProducer)
答案 0 :(得分:0)
如果我正确理解了这个问题,可以使用Kotlin Coroutines如下实现它:
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
答案 1 :(得分:0)
对于简单的调度要求,我会使用协程实现它,因为它很有趣:
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)
}
}