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

Java中Timer与TimerTask配合循环实现限时输入功能报错排查

问题:Timer已取消导致的IllegalStateException异常

需求逻辑:循环中给用户5秒输入时间,输入"atk"则从HP中减去随机数,输入其他内容则HP增加随机数,直到HP为0时终止程序。但运行代码时抛出java.lang.IllegalStateException: Timer already cancelled异常。

原代码

import java.util.Scanner;
import java.util.Timer;
import java.util.TimerTask;
import java.util.Random;

public class Main {

    public static void main(String[] args) {
        int hp = 60;
        Scanner sc = new Scanner(System.in);
        Random los = new Random();
        int pc = 1 + los.nextInt(4);
        Timer czas = new Timer();
        do{
            TimerTask zd = new TimerTask(){
                public void run(){
                    System.out.println("Czas off");
                    System.exit(0);
                }
            };
            czas.schedule(zd, 5 * 1000);
            System.out.println("5 sek na odp");
            String odp = sc.nextLine();
            switch(odp){
                case "atk":
                    System.out.println("oo tak");
                    hp = hp - pc;
                    System.out.println("hp spadlo o " + pc + " "  + " wynosi " + hp);
                    czas.cancel();
                    break;
                default:
                    System.out.println("zle");
                    czas.cancel();
                    hp = hp + pc;
                    System.out.println("hp wzroslo o " + pc);
            }
        } while (hp > 0);
        System.out.println("pokonany");
    }
}

控制台报错日志

5 sek na odp
atk
oo tak
hp spadlo o 1  wynosi 59
Exception in thread "main" java.lang.IllegalStateException: Timer already cancelled.
        at java.base/java.util.Timer.sched(Unknown Source)
        at java.base/java.util.Timer.schedule(Unknown Source)
        at Main.main(Main.java:26)

[Program finished]

错误原因

Timer对象一旦调用cancel()方法就会被永久终止,无法再复用做新的任务调度。原代码中Timer czas是在循环外初始化的,第一次循环执行czas.cancel()后,这个Timer就失效了,第二次循环再调用czas.schedule()时就会抛出异常。

另外原代码中pc随机数只生成一次,每次加减的数值都一样,不符合“随机数”的需求,也需要修正。

修复后的代码

import java.util.Scanner;
import java.util.Timer;
import java.util.TimerTask;
import java.util.Random;

public class Main {

    public static void main(String[] args) {
        int hp = 60;
        Scanner sc = new Scanner(System.in);
        Random los = new Random();
        
        do{
            // 每次循环新建Timer,避免复用已取消的Timer
            Timer czas = new Timer();
            // 每次循环重新生成随机数,确保每次加减的数值随机
            int pc = 1 + los.nextInt(4);
            
            TimerTask zd = new TimerTask(){
                public void run(){
                    System.out.println("Czas off");
                    System.exit(0);
                }
            };
            czas.schedule(zd, 5 * 1000);
            System.out.println("5 sek na odp");
            String odp = sc.nextLine();
            
            // 先取消当前Timer任务,避免超时触发退出
            czas.cancel();
            
            switch(odp){
                case "atk":
                    System.out.println("oo tak");
                    hp = hp - pc;
                    System.out.println("hp spadlo o " + pc + " wynosi " + hp);
                    break;
                default:
                    System.out.println("zle");
                    hp = hp + pc;
                    System.out.println("hp wzroslo o " + pc);
            }
        } while (hp > 0);
        System.out.println("pokonany");
    }
}

修复说明

  1. 将Timer czas的创建移到do-while循环内部,每次循环都生成新的Timer实例,避免复用已被取消的Timer。
  2. 将随机数pc的生成移到循环内部,确保每次循环的加减数值都是随机的。
  3. 在处理用户输入后先调用czas.cancel(),统一取消当前Timer任务,避免代码重复。

内容的提问来源于stack exchange,提问作者DraggyCords cords

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.08 12:10:18