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

引言

由于项目中有处理大量后台任务并且串行执行的需求,特意写了一个简易的任务调度器,方便监控每个任务执行和异常情况,任务之间互不影响。正如上所述,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密集型任务的瓶颈。
  • 3
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
好的,下面是一个使用 Kotlin 和 Spring Boot 写的简单的 Socket 服务的例子: 首先,我们需要添加对 Spring Boot 和 Kotlin 的依赖,我们可以在 `build.gradle` 文件中添加以下内容: ```groovy dependencies { implementation("org.springframework.boot:spring-boot-starter-websocket") implementation("org.jetbrains.kotlin:kotlin-stdlib-jdk8") } ``` 接下来,我们可以创建一个 `WebSocketController` 类,用来处理 WebSocket 的请求: ```kotlin import org.springframework.stereotype.Controller import org.springframework.web.bind.annotation.GetMapping import org.springframework.web.bind.annotation.RequestMapping import org.springframework.web.bind.annotation.ResponseBody import org.springframework.web.socket.WebSocketHandler import org.springframework.web.socket.config.annotation.EnableWebSocket import org.springframework.web.socket.config.annotation.WebSocketConfigurer import org.springframework.web.socket.config.annotation.WebSocketHandlerRegistry import org.springframework.web.socket.server.standard.ServletServerContainerFactoryBean @Controller @EnableWebSocket @RequestMapping("/socket") class WebSocketController : WebSocketConfigurer { override fun registerWebSocketHandlers(registry: WebSocketHandlerRegistry) { registry.addHandler(SocketHandler(), "/socket-handler") } @GetMapping("/test") @ResponseBody fun test(): String { return "Hello World!" } // 设置 WebSocket 缓冲区的大小 fun servletServerContainerFactoryBean(): ServletServerContainerFactoryBean { val servletServerContainerFactoryBean = ServletServerContainerFactoryBean() servletServerContainerFactoryBean.maxBinaryMessageBufferSize = 1024 * 1024 servletServerContainerFactoryBean.maxTextMessageBufferSize = 1024 * 1024 return servletServerContainerFactoryBean } } class SocketHandler : WebSocketHandler { override fun afterConnectionEstablished(session: WebSocketSession) { println("Connection established!") } override fun handleMessage(session: WebSocketSession, message: WebSocketMessage<*>) { println("Received message: ${message.payload}") } override fun handleTransportError(session: WebSocketSession, exception: Throwable) { println("Transport Error!") } override fun afterConnectionClosed(session: WebSocketSession, closeStatus: CloseStatus) { println("Connection closed!") } override fun supportsPartialMessages(): Boolean { return false } } ``` 在上面的代码中,`WebSocketController` 类实现了 `WebSocketConfigurer` 接口,用来注册 WebSocket 的处理程序。同时,我们还定义了一个 `SocketHandler` 类,用来处理 WebSocket 的消息。在 `WebSocketController` 类中,我们还定义了一个测试用的 API,用来返回一个字符串。 最后,我们需要在 `application.properties` 文件中配置 Tomcat 的 WebSocket 支持: ``` server.tomcat.max-connections=1000 server.tomcat.max-threads=200 server.tomcat.accept-count=200 server.tomcat.max-http-post-size=10000000 server.tomcat.max-swallow-size=10000000 ``` 在上面的配置中,我们设置了 Tomcat 的最大连接数、最大线程数、最大 HTTP POST 大小等等。 以上就是一个简单的使用 Kotlin 和 Spring Boot 写的 Socket 服务的例子,你可以根据自己的需求进行修改和扩展。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值