From 8132a1ab4cca69ef34593a8ba3f24a954a871aef Mon Sep 17 00:00:00 2001 From: dongRogen <3601778801@qq.com> Date: Tue, 26 Jul 2022 01:03:41 +0800 Subject: [PATCH] =?UTF-8?q?=E6=B7=BB=E5=8A=A0=E4=BB=BB=E5=8A=A1=E8=B0=83?= =?UTF-8?q?=E5=BA=A6=E5=B7=A5=E5=85=B7=20-=20=E6=97=B6=E5=88=BB=E8=A1=A8?= =?UTF-8?q?=E3=80=81=E4=BB=BB=E5=8A=A1=E8=A1=A8=20-=20=E5=BE=AA=E7=8E=AF?= =?UTF-8?q?=E6=89=A7=E8=A1=8C?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../top/jie65535/jcf/ScheduleHandler.kt | 149 ++++++++++++++++++ 1 file changed, 149 insertions(+) create mode 100644 src/main/kotlin/top/jie65535/jcf/ScheduleHandler.kt diff --git a/src/main/kotlin/top/jie65535/jcf/ScheduleHandler.kt b/src/main/kotlin/top/jie65535/jcf/ScheduleHandler.kt new file mode 100644 index 0000000..cbca4b9 --- /dev/null +++ b/src/main/kotlin/top/jie65535/jcf/ScheduleHandler.kt @@ -0,0 +1,149 @@ +package top.jie65535.jcf + +import net.mamoe.mirai.Bot +import net.mamoe.mirai.console.command.ConsoleCommandSender.name +import net.mamoe.mirai.utils.MiraiLogger +import top.jie65535.jcf.util.LockUtil +import java.util.* +import kotlin.concurrent.thread + +/** + * 任务调度 + * + * @property bot 每个 bot 维护一个调度器 + * @property logger 日志 + */ +class ScheduleHandler(private val bot: Bot, private val logger: MiraiLogger) { + // region -- 常量、变量 + /** + * 任务表 + */ + private val taskSet = mutableMapOf Unit>() + + /** + * 时刻表; + * 仅时与分用于校对 + */ + private val periodList = mutableListOf() + + /** + * 线程锁:时刻表 + */ + private val periodLock = LockUtil(periodList) + + /** + * 线程锁:任务表 + */ + private val taskLock = LockUtil(taskSet) + + // 变量 + + /** + * 标识:暂停校对和调度 + */ + private var pause = true + + /** + * 暂存 + */ + private var swap: Calendar? = null + + /** + * 线程:循环执行核对与调度 + */ + private val loopThread = thread(name = "schedule:${bot.id}:${bot.nick}") { loop() } + + // endregion + + // region -- 校对与调度 + + /** + * 比较时与分是否相等 + */ + private infix fun Calendar.eq(then: Calendar?): Boolean = + if (then == null) + false + else get(Calendar.MINUTE) == then.get(Calendar.MINUTE) + && get(Calendar.HOUR_OF_DAY) == then.get(Calendar.HOUR_OF_DAY) + + /** + * 取反 [eq] 函数 + */ + private infix fun Calendar.neq(then: Calendar): Boolean = !eq(then) + + /** + * 暂存的时刻重入时刻表 + * + * @param ref 用以校准的指标 + */ + private fun reSwap(ref: Calendar) { + if (ref eq swap) { + periodLock.withLock { add(swap!!) } + swap = null + } + } + + /** + * 时辰到? + * + * @param then 校对时刻 + */ + private fun isThen(then: Calendar): Boolean = periodLock.withLock { + var isNow = false + val ii = periodList.iterator() + while (ii.hasNext()) { + val time = ii.next() + if (then eq time) { + isNow = true + swap = time + ii.remove() + break + } + } + isNow// return value + } + + /** + * 等待 + * + * @receiver 当前线程 + * @param time 等待时间(毫秒) + * @return 是否继续 + */ + private fun Thread.delay(time: Long): Boolean = + try { + Thread.sleep(1000 * 20) + true + } catch (_: Exception) { + false + } + + /** + * 循环执行校准与调度 + */ + private fun loop() { + val thread = Thread.currentThread() + while (!thread.isInterrupted) { + if (pause) continue + if (periodList.isEmpty()) continue + if (!thread.delay(1000 * 20)) + break + + val now = Calendar.getInstance() + reSwap(now) + if (!isThen(now)) continue + + taskLock.withLock { + // TODO 异步、限时 + forEach { (id, task) -> task(id) } + } + }// while + logger.info("线程[$name]已结束") + // TODO clean + } + // endregion + + // region -- TODO 参数与状态 + + // endregion +}