Асинхронная плановая работа в Котлине - PullRequest
0 голосов
/ 24 февраля 2019

Я пытаюсь понять, как лучше всего запускать асинхронное задание с запланированной частотой в Kotlin, в то время как приложение обычно выполняет свои обычные задачи.Допустим, у меня есть простое приложение, которое печатает только «...» каждую секунду, но каждые 5 секунд я хочу, чтобы другая работа / поток / сопрограмма (которая когда-либо подходила лучше всего) печатала «у вас есть сообщение!».Для асинхронного задания у меня есть класс NotificationProducer, и он выглядит следующим образом.

class NotificationProducer {

    fun produce() {
        println("You have a message!")
    }
} 

Тогда мой основной метод выглядит следующим образом.

    while (true) {
        println("...")
        sleep(1000)
    }

Должен ли я использовать GlobalScope.asyncTimer().schedule(...) или какая-то кварцевая работа для достижения того, чего я хочу?Любой совет высоко ценится.Дело в том, что уведомление должно приходить из другого класса (например, NotificationProducer)

Ответы [ 2 ]

0 голосов
/ 07 марта 2019

Что касается требований простого планирования, я бы реализовал его с помощью сопрограмм, потому что это забавно:

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")
    }
}

В остальном API параллелизма Java также довольно солиден:

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)
    }
}
0 голосов
/ 06 марта 2019

Если я правильно понимаю проблему, с помощью 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
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...