一个任务队列的轮询执行方案
轮询一般由三部分组成:
-
任务队列的数据结构 -
死循环 -
循环终止条件
下面的例子中,通过 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