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

如何基于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.

🔍 你的当前代码存在的问题

  1. 无限循环阻塞线程:你的Timer.PerfectTimer()是一个无限while(x)循环,永远不会返回值,所以changingStatsOverTime()里的if条件永远不会执行——方法会一直卡在PerfectTimer()的循环里。
  2. 时间计算逻辑错误:当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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.04.29 23:19:03