# ~~mod-延时任务~~ [![](https://img.shields.io/badge/simple--robot-module-green)](https://github.com/ForteScarlet/simple-robot-core) [![](https://img.shields.io/maven-central/v/io.github.ForteScarlet.simple-robot-module/mod-delay-task)](https://search.maven.org/artifact/io.github.ForteScarlet.simple-robot-module/mod-delay-task) ## **介绍** 有些时候,在你收到消息后并不想立即回复,而是想要等待个5秒、10秒、1分钟后再进行答复。 此时,假如你通过 **`Thread.sleep`** 来实现,便会阻塞当前线程,是不可取的。 延时任务模组提供了能够异步处理任务的功能,且同时提供了针对于 **`SETTER`** 与 **`SENDER`** 的延时代理。 >[info] 并没有针对于 **`GETTER`** 的代理,至于为什么没有,我想大概很好理解。 >[danger] 此模组实现逻辑存在严重缺陷,目前可以考虑直接使用Java中的延时队列等方式来实现延时任务而非使用此模组。 ## **使用** ### 1. **依赖导入** (版本可参考文档上方的版本号图标或前往maven仓库查看, 仓库地址:https://search.maven.org/artifact/io.github.ForteScarlet.simple-robot-module/mod-delay-task) #### **Maven** ```xml <dependency> <groupId>io.github.ForteScarlet.simple-robot-module</groupId> <artifactId>mod-delay-task</artifactId> <version>${version}</version> </dependency> ``` #### **gradle** ```gradle compile group: 'io.github.ForteScarlet.simple-robot-module', name: 'mod-delay-task', version: '${version}' ``` <br> ### 2\. **普通工具类** 此模组中提供了一个工具类:**`com.simplerobot.modules.delay.DelayHelper`** 类。 其为一个单例,可通过 **`INSTANCE`** 或者 **`getInstance()`** 得到他的实例。预计在核心 **`1.12.x`** 之后可自动注入。 此工具类提供了一个方法 **`delayTask(...)`** 及其若干重载。此方法代表了:延迟一定时间后执行任务,默认时间类型为秒。 你可以这样使用: ```java public static void main(String[] args) { // 获取工具类实例 final DelayHelper delayHelper = DelayHelper.getInstance(); // 定义一个Runnable实例,就像创建线程的时候那样 Runnable task = () -> System.out.println("延迟了!"); // 2秒后执行任务 delayHelper.delayTask(task, 2); // 4000毫秒后执行任务 delayHelper.delayTask(task, 4000, TimeUnit.MILLISECONDS); // 2分钟后执行任务 delayHelper.delayTask(task, 2000, TimeUnit.MINUTES); //v1.1-1.12后增加: // runnable任务数组 Runnable[] rs = new Runnable[]{ () -> System.out.println("hi1"), () -> System.out.println("hi2"), () -> System.out.println("hi3"), () -> System.out.println("hi4") }; //runnable任务迭代器 Iterator<Runnable> iter = Arrays.asList(rs).iterator(); // 使用迭代器,每个任务执行前等待1秒,时间类型默认为秒 instance.delayTaskIter(1, iter); // 使用数组,每个任务执行前等待2000毫秒,如果不填则时间类型默认为秒 instance.delayTask(2000, TimeUnit.MICROSECONDS, rs); Iterator<Runnable> iter = Arrays.asList(rs).iterator(); // 单独使用此工具类的时候,他并不会像Thread一样,在主线程结束后依旧存活,所以需要只少保证jvm处于存活状态 while(true){ // 保持jvm存活 } } ``` ### 3\. **SETTER/SENDER 代理** 当你的项目中存在 **`simple-robot-core`**或者**任意一个组件**(例如`cqhttp组件`)的时候,你便可以使用 **`SETTER`** 和 **`SENDER`** 的代理了。 >[info] 毕竟如果连core框架依赖都没有,你去代理谁啊? 使用SETTER / SENDER代理,首先你需要有一个原本的SETTER / SENDER对象,然后以其为构造参数的参数之一传递进去。 SETTER代理对应的类为 **`DelaySetter`** SENTER代理对应的类为 **`DelaySender`** 它们的使用方法基本一致,以下使用 **`DelaySender`** 为例: ```java @Beans public class TestListener { @Listen(MsgGetTypes.privateMsg) public void testListen(PrivateMsg msg, MsgSender sender){ // 延迟送信器,参数2为时间,默认为秒。可选参数三同DeplyHelper的方法,是时间的格式。 DelaySender delaySender = new DelaySender(sender.SENDER, 2); // DelaySender delaySender = new DelaySender(sender.SENDER, 2000, TimeUnit.MILLISECONDS); // 使用毫秒 // 2秒后复读一次 delaySender.sendPrivateMsg(msg.getCode(), "2秒后: " + msg.getMsg()); // 10秒后再复读一次 // 重新设置时间, 注意!此处设置的时间格式默认为毫秒,所以需要添加时间格式,或者使用10*1000 delaySender.setDelayTime(10, TimeUnit.SECONDS); // 延时发送 delaySender.sendPrivateMsg(msg.getCode(), "10秒后: " + msg.getMsg()); // 用原本的sender先直接发送一个消息 sender.SENDER.sendPrivateMsg(msg.getCode(), "直接发送: " + msg.getMsg()); } } ``` **注意!当你使用延迟送信器的时候,送信器原本的所有返回值均为默认值。如果返回值为String类型,则返回null,如果返回值为Boolean类型,返回true。** 顺带一提,`DelaySender`/`DelaySetter` 是依赖于上述的`DelayHelper`工具类实现的。 # 注意事项 此模组版本命名规则类似于组件的命名规则(即`${模组版本}-${核心版本系}`),但是此模组理论上任何版本都可以用,虽然送信器代理有很小的概率会出现一点版本之间的API偏差问题,但是基础工具类`DelayHelper`不会受到核心的影响。 因此此模组在核心的早期版本也可以进行使用。