Java实现Minecraft Bukkit/Spigot插件每5秒重复执行任务
Bukkit/Spigot插件实现5秒重复任务方案
嘿,我来帮你搞定这个每5秒重复执行的任务!在Bukkit/Spigot插件开发里,最稳妥的方式是用官方提供的Bukkit调度器API,比Java原生的Timer更适配服务器环境,不会出现线程安全或者插件卸载后任务还乱跑的问题,咱直接上代码:
import org.bukkit.Bukkit; import org.bukkit.plugin.java.JavaPlugin; import org.bukkit.scheduler.BukkitTask; public class YourPlugin extends JavaPlugin { // 保存任务实例,方便插件禁用时取消,避免内存泄漏 private BukkitTask repeatTask; @Override public void onEnable() { getLogger().info("TBC Enabled"); // 创建每5秒重复执行的任务 repeatTask = Bukkit.getScheduler().runTaskTimer(this, () -> { // ~~ 从此处到下一个注释的代码需要每5秒执行一次 for (org.bukkit.entity.Player player : Bukkit.getOnlinePlayers()) { player.sendMessage("N/A"); } // ~~ 结束需要重复执行的代码块 }, 0L, 100L); // 参数说明: // 0L = 任务启动后立即执行第一次(延迟0秒) // 100L = 每100tick重复一次(Minecraft每秒跑20tick,100tick就是5秒) } @Override public void onDisable() { // 插件禁用时务必取消任务,防止任务继续占用资源 if (repeatTask != null && !repeatTask.isCancelled()) { repeatTask.cancel(); } getLogger().info("TBC Disabled"); } }
关键知识点说明
- Bukkit调度器的优势:默认在服务器主线程执行任务,操作玩家、方块等Bukkit API时不会触发线程安全问题,而且任务会和插件生命周期绑定,管理起来更省心。
- tick的计算:Minecraft服务器每秒固定运行20个游戏tick,所以5秒就是
20 * 5 = 100tick,这是Bukkit任务周期的标准单位。 - 任务取消的必要性:如果不保存任务实例并在
onDisable中取消,插件卸载后任务可能还在后台运行,导致服务器报错或者内存泄漏。
关于Java原生Timer的备选方案(不推荐)
如果你非要用Java原生的Timer实现,一定要注意:Timer的线程是独立于Bukkit主线程的,直接操作Bukkit API会报错,必须把业务逻辑切换到主线程执行,代码示例如下:
import java.util.Timer; import java.util.TimerTask; @Override public void onEnable() { getLogger().info("TBC Enabled"); Timer timer = new Timer(); timer.scheduleAtFixedRate(new TimerTask() { @Override public void run() { // 必须用Bukkit调度器把操作切回主线程! Bukkit.getScheduler().runTask(YourPlugin.this, () -> { for (org.bukkit.entity.Player player : Bukkit.getOnlinePlayers()) { player.sendMessage("N/A"); } }); } }, 0, 5000); // 0毫秒延迟,每5000毫秒(5秒)执行一次 }
这种方式不仅代码更繁琐,还需要自己手动管理Timer的取消(比如在onDisable中调用timer.cancel()),所以还是优先用Bukkit官方的调度器方案哦!
内容的提问来源于stack exchange,提问作者Cheap CPPS




