手写一个轮询实现

一个任务队列的轮询执行方案

轮询一般由三部分组成:

下面的例子中,通过 Kotlin 协程实现了一个自动关闭的轮询任务:

abstract class PollingTask {

    private var finishCallback: (() -> Unit)? = null

    abstract fun run()

    fun realRun() {
        run()
        finishCallback?.invoke()
    }

    fun finishCallback(block: (() -> Unit)?) {
        this.finishCallback = block
    }
}

首先抽象出一个轮询任务的类,因为任务执行可能需要耗时,在这里增加了执行结束的回调,通知轮询开始执行下一个任务。

轮询器的数据结构这里选择的是 LinkedList ,它是个双向链表,可以当队列,可以当栈,十分方便。

下面是轮询器完整的代码:

object Dispatcher {

    private var task: Task? = null

    private var queue: LinkedList<Task> = LinkedList()

    private var pollingJob: Job? = null

    private var isDoing: AtomicBoolean = AtomicBoolean(false)

    private var isPolling = false

    val handler = Handler(Looper.getMainLooper())

    fun dispatch(task: Task) {
        queue.add(task)
        if (!isPolling) {
            startPolling()
        }
    }

    private fun startPolling() {
        pollingJob = CoroutineScope(Dispatchers.IO).launch {
            loop()
        }
        isPolling = true
    }

    private fun stopPolling() {
        isPolling = false
        pollingJob?.cancel()
    }

    private suspend fun loop() {
        while (true) {
            delay(1000)
            // 当队列为空时,自动取消轮询
            if (queue.isEmpty()) {
                Log.i(this.javaClass.name, "正在取消轮询")
                stopPolling()
                return
            }
            // 当前存在任务正在执行,跳过
            if (isDoing.get()) {
                continue
            }
            Log.i(this.javaClass.name, "正在轮询,当前剩余: ${queue.size}")
            task = queue.pop()
            // 任务执行完成,更新状态
            task?.finishCallback {
                isDoing.set(false)
                task = null
            }
            Log.i(this.javaClass.name, "当前剩余: ${queue.size}")

            // 这里可以酌情考虑要不要使用 post
            handler.post {
                task?.realRun()
                isDoing.set(true)
            }
        }
    }
}

这里使用协程去执行轮询,避免造成主线程的阻塞。通过 isDoing 来判断当前是否存在正在执行的任务,如果存在,则阻塞无法执行下一个任务。

isDoing 在这里使用的是 AtomicBoolean ,这是因为可能涉及跨线程,比如任务的执行和结束在主线程,通过原子类处理同步问题。


原文始发于微信公众号(八千里路山与海):手写一个轮询实现

版权声明:本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 举报,一经查实,本站将立刻删除。

文章由极客之音整理,本文链接:https://www.bmabk.com/index.php/post/85029.html

(0)
小半的头像小半

相关推荐

发表回复

登录后才能评论
极客之音——专业性很强的中文编程技术网站,欢迎收藏到浏览器,订阅我们!