Kotlin 中的异步计划作业

wes*_*eyy 2 asynchronous quartz-scheduler kotlin

我试图了解在 Kotlin 中以预定速率触发异步作业的最佳方式是什么,而应用程序通常正在运行它的正常任务。假设我有一个简单的应用程序,它每秒只打印出“...”,但每 5 秒我想要另一个作业/线程/协程(哪个最适合)来打印“你有一条消息!”。对于异步作业,我有一个类NotificationProducer,它看起来像这样。

class NotificationProducer {

    fun produce() {
        println("You have a message!")
    }
} 
Run Code Online (Sandbox Code Playgroud)

然后,我的主要方法看起来像这样。

    while (true) {
        println("...")
        sleep(1000)
    }
Run Code Online (Sandbox Code Playgroud)

我应该使用GlobalScope.async,Timer().schedule(...)还是一些 Quartz 工作来实现我想要的?任何建议都非常感谢。关键是通知必须来自另一个类(例如 NotificationProducer)

Ser*_*gey 6

如果我正确理解了这个问题,使用 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
            }
        }
    }
}
Run Code Online (Sandbox Code Playgroud)

然后您可以使用该类的实例Presenter来启动协程并停止它:

val presenter = Presenter()
presenter.schedule() // calling `schedule()` function launches the coroutine

//...

presenter.cancel() // cancel the coroutine when you need
Run Code Online (Sandbox Code Playgroud)


s1m*_*nw1 5

对于简单的调度需求,可以考虑使用协程:

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")
    }
}
Run Code Online (Sandbox Code Playgroud)

否则,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)
    }
}
Run Code Online (Sandbox Code Playgroud)