如何基于Java自定义Timer类高效实现定时整数扣减功能?
解决定时扣减整数的高效实现方案
Hey there! Let's break down how to fix and optimize your timer-based deduction logic. First, let's look at the issues in your current code, then jump to better implementations.
🔍 你的当前代码存在的问题
- 无限循环阻塞线程:你的
Timer.PerfectTimer()是一个无限while(x)循环,永远不会返回值,所以changingStatsOverTime()里的if条件永远不会执行——方法会一直卡在PerfectTimer()的循环里。 - 时间计算逻辑错误:当
secondspassed达到60时你重置了它,但displayMinutes的递增逻辑会在每秒钟检查secondspassed %60 ==0,这会导致在重置后的下一次循环(secondspassed=0)再次触发displayMinutes++,造成分钟数统计错误。
🚀 推荐方案:使用ScheduledExecutorService(高效且可靠)
Java的java.util.concurrent包提供了ScheduledExecutorService,它是官方推荐的定时任务工具,比手动写循环+sleep更高效、更不容易出错,还能方便地管理任务生命周期。
实现代码
假设你有一个存储整数的类(比如Stats),我们可以这样实现每1分钟扣减25的逻辑:
import java.util.concurrent.Executors; import java.util.concurrent.ScheduledExecutorService; import java.util.concurrent.TimeUnit; // 假设你的Stats类 class Stats { private int tiredness = 0; private int hunger = 0; private int targetValue = 100; // 需要扣减的整数 public void addTiredness() { tiredness += 25; } public void addHunger() { hunger +=25; } // 扣减目标整数的方法 public void decreaseTargetValue() { targetValue -=25; System.out.println("目标整数已扣减25,当前值: " + targetValue); } // getter方法 public int getTargetValue() { return targetValue; } } public class StatsManager { private final Stats stats = new Stats(); private final ScheduledExecutorService scheduler; public StatsManager() { // 创建单线程的定时任务调度器 scheduler = Executors.newSingleThreadScheduledExecutor(); } // 启动定时任务:每1分钟执行一次扣减操作 public void startDeductionTimer() { // 参数说明: // 1. 要执行的任务(lambda表达式) // 2. 初始延迟时间(0秒后开始) // 3. 任务执行间隔(1分钟) // 4. 时间单位 scheduler.scheduleAtFixedRate(() -> { stats.decreaseTargetValue(); stats.addTiredness(); stats.addHunger(); }, 0, 1, TimeUnit.MINUTES); } // 停止定时任务(避免内存泄漏) public void stopTimer() { if (!scheduler.isShutdown()) { scheduler.shutdown(); try { // 等待1分钟让任务优雅停止 if (!scheduler.awaitTermination(1, TimeUnit.MINUTES)) { scheduler.shutdownNow(); } } catch (InterruptedException e) { scheduler.shutdownNow(); Thread.currentThread().interrupt(); } } } public static void main(String[] args) { StatsManager manager = new StatsManager(); manager.startDeductionTimer(); // 模拟程序运行一段时间 try { TimeUnit.MINUTES.sleep(5); } catch (InterruptedException e) { Thread.currentThread().interrupt(); } finally { manager.stopTimer(); } } }
为什么这个方案更好?
- 无需手动计算时间:框架帮你精准管理定时逻辑,避免手动计算秒数/分钟数的错误。
- 非阻塞设计:任务在单独的线程中执行,不会阻塞主线程。
- 可管理生命周期:提供
shutdown()方法优雅停止任务,避免资源泄漏。
🔧 如果你坚持使用自定义Timer循环
如果你想基于自己的循环逻辑实现,需要修正时间计算并使用回调机制(避免阻塞主线程):
修正后的Timer类+回调实现
import java.util.concurrent.TimeUnit; public class CustomTimer { // 定义回调接口,用于通知定时事件 public interface MinuteCallback { void onMinuteElapsed(int minutesPassed); } private final MinuteCallback callback; public CustomTimer(MinuteCallback callback) { this.callback = callback; } public void startTimer() throws InterruptedException { long startTime = System.currentTimeMillis(); int lastMinute = 0; while (true) { TimeUnit.SECONDS.sleep(1); long elapsedMs = System.currentTimeMillis() - startTime; int currentMinute = (int) (elapsedMs / 60000); // 转换为分钟 // 只有当分钟数增加时才触发回调(避免重复触发) if (currentMinute > lastMinute) { lastMinute = currentMinute; callback.onMinuteElapsed(lastMinute); } } } }
主类中使用自定义Timer
public class MainApp { private final Stats stats = new Stats(); public static void main(String[] args) { MainApp app = new MainApp(); app.startCustomTimer(); } public void startCustomTimer() { CustomTimer timer = new CustomTimer(minutesPassed -> { // 每1分钟扣减25 stats.decreaseTargetValue(); stats.addTiredness(); stats.addHunger(); // 如果需要每2分钟执行一次,可以加判断: // if (minutesPassed % 2 == 0) { // stats.decreaseTargetValue(); // stats.addTiredness(); // stats.addHunger(); // } }); // 在单独线程中启动定时器,避免阻塞主线程 new Thread(() -> { try { timer.startTimer(); } catch (InterruptedException e) { Thread.currentThread().interrupt(); System.err.println("定时器被中断: " + e.getMessage()); } }).start(); } }
关键修正点
- 回调机制:Timer类只负责检测时间,具体执行逻辑交给回调接口,解耦定时逻辑和业务逻辑。
- 单独线程运行:避免定时器的无限循环阻塞主线程。
- 准确的分钟判断:通过总毫秒数计算当前分钟,只有当分钟数真正增加时才触发事件,避免重复统计。
内容的提问来源于stack exchange,提问作者Bispar426
相关产品推荐
相关产品推荐

