一个用Kotlin编写简易的串行任务调度器

基于ScheduledExecutorService的两种方法(详解) 下面小编就为大家带来一篇基于ScheduledExecutorService的两种方法(详解)。小编觉得挺不错的,现在就分享给大家,也给大家做个参考。一起跟随小编过来看看吧 立即下载

引言

由于项目中有处理大量后台任务并且串行执行的需求,特意写了一个简易的任务调度器,方便监控每个任务执行和异常情况,任务之间互不影响。正如上所述,Kotlin中的TaskScheduler类提供了一个强大的解决方案,用于使用ScheduledExecutorService异步地排队和执行任务。


使用方法

1.初始化:

val taskListener = object : TaskScheduler.TaskListener {
    override fun beforeExecute(task: TaskScheduler.NamedRunnable) {
        println("开始任务:${task.name}")
    }

    override fun afterExecute(task: TaskScheduler.NamedRunnable, exception: Exception?) {
        println("完成任务:${task.name},异常:$exception")
    }
}
val scheduler = TaskScheduler(taskListener, 5)

2.提交任务:

scheduler.submit("加载数据") {
    // 加载数据的代码
}
scheduler.submit("处理数据") {
    // 处理数据的代码
}

3.优雅关闭:

当所有任务完成后,调度器将在指定的超时后自动关闭,确保不浪费资源。


完整代码

import java.util.concurrent.*
import java.util.concurrent.atomic.AtomicBoolean

class TaskScheduler(private val listener: TaskListener? = null, private val timeout: Long = 5) {
    private val taskQueue = ConcurrentLinkedQueue<NamedRunnable>()
    private val isTaskRunning = AtomicBoolean(false)
    private var executorService: ScheduledExecutorService? = null
    private var scheduledShutdownFuture: ScheduledFuture<*>? = null

    @Synchronized
    fun submit(name: String, task: Runnable) {
        ensureExecutorService()
        taskQueue.offer(NamedRunnable(name, task))

        // 取消之前安排的关闭任务
        scheduledShutdownFuture?.cancel(false)

        if (isTaskRunning.compareAndSet(false, true)) {
            executorService?.submit { processTasks() }
        }
    }

    private fun processTasks() {
        try {
            while (taskQueue.isNotEmpty()) {
                val nextTask = taskQueue.poll()
                listener?.beforeExecute(nextTask)
                var exception: Exception? = null
                try {
                    nextTask.run()
                } catch (e: Exception) {
                    exception = e
                }
                listener?.afterExecute(nextTask, exception)
            }
        } finally {
            scheduleShutdown()
        }
    }

    private fun ensureExecutorService() {
        if (executorService == null || executorService!!.isShutdown) {
            executorService = Executors.newSingleThreadScheduledExecutor()
        }
    }

    private fun scheduleShutdown() {
        // 在设置定时关闭之前,先重置 isTaskRunning 标志
        isTaskRunning.set(false)

        // 如果队列为空,且没有正在运行的任务,则安排关闭执行器
        if (taskQueue.isEmpty() && !isTaskRunning.get()) {
            scheduledShutdownFuture = executorService?.schedule({
                executorService?.shutdown()
                executorService = null
                listener?.onShutdown()
            }, timeout, TimeUnit.SECONDS)
        }
    }

    interface TaskListener {
        fun beforeExecute(task: NamedRunnable)
        fun afterExecute(task: NamedRunnable, exception: Exception?)
        fun onShutdown()
    }

    class NamedRunnable(val name: String, private val task: Runnable) : Runnable {
        override fun run() {
            task.run()
        }
    }
}

最后

简要概括下优缺点:

  • 资源自动管理,超时自动释放资源
  • 任务命名,更清晰的了解每个任务执行情况
  • 线程安全,不用担心多线程添加任务导致顺序紊乱

优点:

  • 灵活性:允许动态添加任务,并根据任务负载需要创建或关闭执行器,从而管理执行器的生命周期。

缺点:

  • 单线程限制:当前实现使用单线程执行器,这意味着任务是顺序执行的,而不是并行执行。这可能是CPU密集型任务的瓶颈。
深入解析USB3.0一致性测试的关键技术与实践指南 本文深入解析了USB3.0一致性测试的核心技术与实践指南。文章阐述了测试如何确保设备在5Gbps高速传输下的信号完整性、电源管理合规性及协议兼容性,并提供了从测试系统搭建到完整流程执行的实战经验,帮助工程师有效应对高速信号、电源与兼容性三大核心挑战。 阅读详情

相关推荐

UWB定位原理详细介绍

Hello大家好我是小智,今天我来给大家介绍下超宽带的定位原理,首先我们来讲下什么是UWB技术。 超宽带(Ultra Wide Band)简称UWB,和我们熟悉的WIFI、蓝牙技术一样属于通信技术的一种,UWB是一种无线载波通信技术,它不采用正弦载波,而是利用纳秒级的非正弦波窄脉冲传输数据,其所占的频谱范围很宽,右图是一种典型的正弦载波信号图。 UWB这种技术有什么特点呢? UWB系统结构实现简单;2.具有高速的数据传输能力;3.功耗低;4.安全性高;5.多径分辨能力强;6.可用于精确定位等特点。 UWB.

qq_35699674的博客 2万+

Android——定时器轮询

时间片轮询

Yawn 1925

STM32F103ZET6驱动57闭环步进电机(连线+代码)

一、设备: 1. STM32F103开发板 (普中F103的板子) 2. 57闭环电机带驱动 3. 24V/3A的直流电源,用于给电机驱动供电 简单说明:使用Keil5编程,主要使用了PWM波,外部中断和时间中断,按键控制电机使能和脱机并且控制PWM的周期,调节周期即调节电机的转速。 二、STM32开发板与电机驱动的连线: 1.PUL-、ENA-、DIR-与STM32的连接方法: 可以参考CSND的这个链接中的说明,使用共阴极接法:STM32F407-用TB6600驱动器驱动57步进电机(代码

baidu_39071234的博客 7430

【面试必知】Kotlin并行任务/线程同步的几种实现方式

多线程开发中,经常会遇到这样的需求: Task1、Task2 等多个任务并行执行,等待全部执行完成后,执行Task3。 我们在Kotlin种可以有多种方法实现,在这里一并列举一下: 1. Thread.join 2. synchronized 3. ReentrantLock 4. BlockingQueue 5. CountDownLatch 6. CyclicBarrier 7. CAS 8. Future 9. CompletableFuture 10. Rxjava 11. Coroutine

移动端开发干货分享 6752

BeautyGAN: Instance-level Facial Makeup Transfer with Deep Generative Adversarial Network(2018,妆容迁移)

论文下载地址:BeautyGAN | Proceedings of the 26th ACM international conference on Multimedia 目的:在实例级实现化妆图像和非化妆图像的妆容迁移 方法:全局域集损失和本地实例级损失合并到一个双输入/输出对抗生成网络。步骤:使用一对鉴别器将非化妆面传输到化妆域,鉴别器从域的真实样本中分辨出生成的图像。在域集迁移的基础上,采用基于不同人脸区域的像素级直方图损失来实现实例级迁移。为了保持人脸的一致性和消除伪影,在总体目标函数中加入了.

weixin_53965540的博客 663

1.用Python写了一个进销存管理的软件~需求分析&界面设计&数据库设计&技术路线选择~

前端也打算用Python来写,查了很多的python库,大家比较推荐的是wxpython和QPython,之前接触过一点点的QT,确实非常强大,但是库比较重量级,自己写的这个东西明显配不上QT,又详细调研了一下wxpython,就是它了!

pepper_lihui的专栏 4321

【Kotlin】Gradle中的任务

编写一个Task 任务的依赖 Task的生命周期 Tasks任务集 Gradle的默认任务 Gradle属性 Gradle默认任务

Errol's Blog 1784

DTS 数据迁移

支持关系型数据库(MySQL, Oracle, SQL Server等)、NoSQL数据库、大数据系统等。DTS数据迁移是现代化数据架构调整和云迁移过程中的重要工具,能够大大降低数据迁移的复杂度和风险。DTS (Data Transmission Service) 是一种数据迁移和同步服务,:先迁移历史数据(全量),再实时同步新增变化(增量):不同数据库类型间迁移,如Oracle到MySQL。:将单库数据迁移到分库分表架构。:将业务数据迁移到分析型数据库。:将本地数据库迁移到云数据库。

qq_41081716的博客 749

Android kotlin定时器用法及说明

kotlin定时器 java.util.Timer 定时器 schedule(TimerTask task, long delay) 延迟delay毫秒后,执行一次task schedule(TimerTask task, long delay, long period) 延迟delay毫秒后,执行第一次task,然后每隔period毫秒执行一次task delay为0表示没有延迟,立即执行一次task Timer().schedule(object : TimerTask() {

吕氏春秋i 1万+

卫星测试科普(三):卫星载荷的核心测试设备探秘

总的说来,卫星芯片与元器件,部组件与单机,整机与子系统,系统与整星的设计、定型、制造、验证、总装、发射、在轨等环节都离不开各种测试场景,对于这些卫星测试场景而言,“射频三大件”与高速数字示波器是构成强大测试系统的基础。卫星通信信号生成:覆盖Ka、Q等波段,具备扫频、脉冲、数字调制、噪声信号、雷达信号、数据链信号、OFDM 等多种信号库,用于测试和验证卫星电子设备的电气性能、频率响应、抗干扰能力等。卫星的通信需要高效、快速地传输大量数据,高速信号的质量至关重要,如果卫星信号不佳,卫星就会出现故障或者隐患。

spwbjss的博客 2318

Grafana图像渲染插件安装全攻略:解决依赖缺失问题(附完整命令清单)

本文详细介绍了在CentOS/RHEL环境下安装Grafana图像渲染插件`grafana-image-renderer`的全过程,包括解决常见的依赖缺失问题。通过提供完整的命令清单和疑难问题排查指南,帮助用户高效部署和优化插件性能,确保图像渲染功能稳定运行。

weixin_30399821的博客 86

Kotlin协程-Scheduler的优秀设计

在仔细分析协程源码后,发现kotlin中协程的很多设计都参考了golang中的实现。 比如跟线程和任务调度关系最密切的 Scheduler 类,在它的注释中看到这句话, * The original idea with a single-slot LIFO buffer comes from Golang runtime scheduler by D. Vyukov. * It was proven to be "fair enough", performant and generally well ac

瞎猫实验室 882

基于 Simulink 的**单相全桥 LLC 谐振双向 DC-DC 变换器(带软开关特性)**实战教程

原边(Primary):全桥逆变电路(4个 MOSFET/IGBT),将直流斩波为高频方波。变压器:提供电气隔离和电压变比。副边(Secondary):全波或全桥整流电路(同步整流或二极管)。

xiaoheshang_123的博客 54

kotlin协程并发/并行与串行互相切换,CoroutineScope与await

runBlocking 内部启动的3个协程做耗时操作,从输出可以看到3个协程交叉并发执行,runBlocking 会等到3个协程执行结束后才退出,输出结果有明确先后顺序。一般编程的技法,比如,在Android中,假设在主线程中实现了一个函数,但该函数是耗时操作,毫无疑问,需要将这个函数的实现切入非主线程中操作,那么可以设计一种托管的函数,在托管的函数里面干脏活,处理完成后,把结果抛到主线程。结果1-a: 5 - tid:22。结果1-b: 5 - tid:24。结果2-a: 9 - tid:22。

Zhang Phil 1920

VB摄像头监控

该VB模块可对摄像头捕获的画面进行录像等,可在创建的窗口进行控制

IDEA的使用指南

IDEA基于java的使用手册,可以最快速的上手,在使用中不断的丰富自己的使用技巧.

Kotlin 协程:串行/并行请求、async/await、coroutineScope 管理并发、重试机制

串行/并行请求、async/await、coroutineScope 管理并发、重试机制

学习的最佳方式,就是把它写下来! 368

精雕软件(JDpaint) 5.5 绿色版

精雕软件(JDpaint) 5.5 绿色版精雕软件(JDpaint) 5.5 绿色版精雕软件(JDpaint) 5.5 绿色版

一个简易的并行任务调度器

当你需要在程序中处理大量同类型的耗时任务,并且需要监听每个任务的工作状态和任务的编号,能及时响应并处理错误,而且需要所有任务都执行完毕自动通知时,那么这个任务调度器就非常适合你!一个用Kotlin编写简易的串行任务调度器可以根据你的需求自由定义线程池最大线程数资源自动管理,超时自动释放资源,新加任务自动创建线程池。自定义超时时间,可以延迟线程池资源释放,等待新任务到来,合理利用。

WriteBug001的博客 617

【JUC】串行、并行、并发傻傻搞不懂?一篇讲透

任务严格按照。

L1951381654的博客 639

Kotlin协程Flow实战:用buffer+优先级队列实现批次任务调度

在构建高并发异步任务流时,Kotlin协程的Flow提供了强大的背压与缓冲能力,而如何将批次任务与优先级调度有机结合,是许多开发者面临的真实挑战。Flow中的buffer并非简单缓存,它通过内置Channel实现上下游解耦,配合capacity与onBufferOverflow策略,可精细控制任务流动节奏。然而,仅靠buffer无法解决“批次内优先级最高者先执行”的业务需求,需要引入优先级队列对任务进行二次排序。本文从Flow的背压原理出发,对比sorted、PriorityQueue与自定义调度器的优劣,

weixin_32006655的博客 196

Kotlin 协程一 —— 协程 Coroutine

Go、Python 等很多变成语言在语言层面上都实现协程,java 也有三方库实现协程,只是不常用, Kotlin 在语言层面上实现协程,对比 java, 主要还是用来解决异步任务线程切换的痛点。 协程基于线程,但相对于线程轻量很多,可理解为在用户层模拟线程操作; 每创建一个协程,都有一个内核态线程动态绑定,用户态下实现调度、切换,真正执行任务的还是内核线程。 线程的上下文切换都需要内核参与,而协程的上下文切换,完全由用户去控制,避免了大量的中断参与,减少了线程上下文切换与调度消耗的资源。

金戈鐡馬 5485

【Kotlin】协程的字节码原理

协程是Koltin语言最重要的特性之一,也是最难理解的特性。网上关于kotlin协程的描述也是五花八门,有人说它是轻量级线程,有人说它是无阻塞式挂起,有人说它是一个异步框架等等,众说纷芸。

devnn的专栏 1004

kotlin协程的简述和使用

为什么会有协程、什么是协程、部分语言对于协程支持、kotlin协程、suspend关键字介绍和使用。

Selfishnessness的博客 1717

Android 启动优化(四):手写一个启动任务调度框架(完整源码)

摘要(148字): 本文提出自研启动框架LaunchFlow,规避AnchorTask的10大生产坑。核心创新:延迟提交、主线程任务同步执行+超时降级、环检测3秒定位、分层耗时监控、异常强制放行。5个文件320行无依赖,支持按进程裁剪、可单测。强调独立线程池、避免主线程任务、显式超时设置,确保启动稳定高效。附自动化测试与上线六件事,保障生产可用性。

ezview_uniview的博客 492

Kotlin中协程的使用及挂起恢复原理分析

kotlin中协程的使用及原理分析 1.协程与普通方法任务调度对比 1.执行串行任务 1.普通方式执行 在子线程中执行耗时操作后,通过接口回调来回调结果,当多个任务串行依赖的时候,就会出现 “回调地狱” object Normal{ private const val TAG = "Normal" fun startSerialTask(){ request1 { result1 -> request2(result1,callback

lentolove的博客 865

Kotlin协程runBlocking深度解析:原理、坑与正确用法

现代异步编程中,Kotlin协程通过挂起函数提供了高效的并发模型,而runBlocking作为连接普通函数与协程世界的桥梁,常被误用为万能同步工具。它通过阻塞当前线程并依赖事件循环调度任务,既能实现同步等待,也可能导致Android主线程卡顿或线程池饥饿死锁。理解其底层机制和适用边界,是工程实践的关键。在main入口、单元测试或桥接阻塞API时,runBlocking是合理选择;而在业务链路或UI层,应优先使用lifecycleScope、viewModelScope等安全作用域。从源码行为到真实踩坑案例,

weixin_33851177的博客 444

【WorkManger】使用WorkManager来处理后台任务(Kotlin版)(一)

使用WorkManager来处理后台任务(Kotlin版)(一) 原文地址: 《Background Work with WorkManager - Kotlin》 1 简介 在Android开发中有很多用于处理延迟处理的后台任务的方式。这个代码实验室(codelab)涵盖了WorkManager(一个向后兼容的、灵活的、简单易用的、用于延迟处理后台任务的代码库(library))的用法。 什...

景叁的专栏 1458
上一篇: 在安卓应用中实现Socket通信:创建服务端和客户端
下一篇: 记一次安卓“Low on memory“崩溃问题
_蓝橙
博客等级 码龄7年 1179粉丝 174原创
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

当前余额3.43元 前往充值 >
需支付:10.00元
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付元
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值