You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何取消已调度的Java Timer定时任务并重新运行?Minecraft Forge开发问题

问题根源

修改后取消逻辑不生效的核心原因是变量作用域错误:
你在K键触发的启动逻辑中,新创建的Timer是局部变量,仅在当前if代码块内生效,KeyBind类的成员变量timer仍指向最初创建、已经被取消的旧实例。按下L键执行取消时,调用的是旧实例的cancel()方法,自然无法终止新启动的定时任务。

修复方案

核心修改点

  1. 启动任务时直接给成员变量timer赋值,不要声明局部变量
  2. 新增非空判断避免空指针异常
  3. 可选优化:给状态变量和Timer变量加volatile修饰,保证多线程场景下的变量可见性
  4. 可选优化:TimerTask的死循环中加入小段休眠,降低CPU占用

修复后代码

KeyBind类代码

public class KeyBind {
    // 加volatile保证多线程可见性
    public static volatile Boolean Status = false;
    volatile Timer timer = new Timer();

    @SubscribeEvent
    public void onKeyPressed(InputEvent.KeyInputEvent event) throws InterruptedException {
        // K键启动逻辑
        if (ForgeMain.keybinding.isKeyDown()) {
            if(Status == false) {
                EntityPlayerSP entityPlayerSP = (Minecraft.getMinecraft()).thePlayer;
                entityPlayerSP.addChatComponentMessage((IChatComponent) new ChatComponentText(EnumChatFormatting.YELLOW + "You have successfully ran the NetherWart Macro!"));
                Status = true;
                // 直接给成员变量赋值,不要声明局部Timer
                timer = new Timer();
                timer.schedule(new Left(), 100, 38000);
                timer.schedule(new Forward(), 33100, 38000);
                timer.schedule(new Right(), 35100, 38000);
            }
        }
        // L键取消逻辑
        if(ForgeMain.keybinding1.isKeyDown()){
            if(Status == true) {    
                Status = false;
                System.out.println(Status.booleanValue());
                // 加非空判断避免空指针
                if (timer != null) {
                    timer.cancel();
                    timer.purge();
                }
            }
        }
    }
}

TimerTask优化(可选,降低CPU占用)

public class Right extends TimerTask {
    @Override
    public void run() {
        int keyCode = Minecraft.getMinecraft().gameSettings.keyBindRight.getKeyCode();
        long oldTime = System.currentTimeMillis();
        KeyBinding.setKeyBindState(keyCode, true);
        while (System.currentTimeMillis() - oldTime < 33000) {
            // 加10ms休眠,几乎不影响操作手感,大幅降低CPU占用
            try {
                Thread.sleep(10);
            } catch (InterruptedException e) {
                // 任务被中断时直接释放按键,退出循环
                break;
            }
        }
        KeyBinding.setKeyBindState(keyCode, false);
    }
}

内容的提问来源于stack exchange,提问作者Can Tam

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.10.12 11:24:03