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

Java TimerTask运行时检查实现咨询及代码问题排查

Hey there! Let's work through your code step by step—you've got a solid goal in mind, but there are a few critical missteps keeping it from working right, plus some habits we can clean up to make your code more reliable.

First, the Big Showstopper: You Put Logic in the Wrong Place

The most critical issue is that all your scheduled check logic lives in the RepeatCheckerTask constructor. Remember: Timer.scheduleAtFixedRate is designed to run the run() method of your task on a fixed interval. The constructor only executes once, when you create the task instance. Right now, your code isn't running checks every 10 seconds—it's spawning hundreds of task instances (thanks to that loop in main) and running the constructor logic once per instance, which is a huge waste of resources and not what you want.

Bad Habits & Bugs in Your Current Code

Let's break down the other issues:

  • Overusing static variables: counter, twoMinuteCounter, and noDuplicates are all static, meaning every task instance shares the same values. This leads to messy, unpredictable logic, and they're also thread-unsafe (no synchronization between your main thread and the timer's background thread).
  • Inefficient duplicate checking: Your nested loops have an O(n²) time complexity—slow, especially as your input list grows. A Map can count duplicates in O(n) time instead.
  • Infinite task spawning: The while(RepeatCheckerTask.twoMinuteCounter < 1) loop in main keeps calling scheduleAtFixedRate, creating a flood of task instances that will tank your CPU usage.
  • Unsafe state sharing: The static noDuplicates variable isn't synchronized, so your main thread might not see changes made by the timer thread right away (or at all, in some cases).
Fixed & Improved Implementation

Let's rewrite this to meet your goal: checking if any number is entered 5 times within a 2-minute sliding window, and stopping input if that happens. We'll fix the timer logic, add proper time tracking, and clean up the code.

import java.util.*;
import java.util.concurrent.atomic.AtomicBoolean;
import java.util.stream.Collectors;

class RepeatCheckerTask extends TimerTask {
    // Helper class to track each number and when it was entered
    public static class NumberWithTimestamp {
        int value;
        long timestamp;

        public NumberWithTimestamp(int value, long timestamp) {
            this.value = value;
            this.timestamp = timestamp;
        }
    }

    private final List<NumberWithTimestamp> numberList;
    private final AtomicBoolean noDuplicates;
    private static final int WINDOW_SECONDS = 120; // 2 minutes
    private static final int DUPLICATE_LIMIT = 5;

    public RepeatCheckerTask(List<NumberWithTimestamp> numberList, AtomicBoolean noDuplicates) {
        this.numberList = numberList;
        this.noDuplicates = noDuplicates;
    }

    @Override
    public void run() {
        // Only run checks if we haven't already found a violation
        if (!noDuplicates.get()) return;

        long currentTime = System.currentTimeMillis();
        Map<Integer, Integer> recentCount = new HashMap<>();

        // Count numbers entered in the last 2 minutes
        for (NumberWithTimestamp entry : numberList) {
            if (currentTime - entry.timestamp <= WINDOW_SECONDS * 1000) {
                recentCount.put(entry.value, recentCount.getOrDefault(entry.value, 0) + 1);
                // Trigger violation if we hit the duplicate limit
                if (recentCount.get(entry.value) == DUPLICATE_LIMIT) {
                    noDuplicates.set(false);
                    System.out.println("Banned! You entered the same number 5 times within 2 minutes.");
                    return;
                }
            }
        }
    }
}

public class Testing {
    public static void main(String[] args) {
        List<RepeatCheckerTask.NumberWithTimestamp> numberList = new ArrayList<>();
        Scanner input = new Scanner(System.in);
        Timer timer = new Timer();
        AtomicBoolean noDuplicates = new AtomicBoolean(true);
        final int MAX_INPUTS = 10;

        // Schedule the task ONCE to run every 10 seconds
        timer.scheduleAtFixedRate(new RepeatCheckerTask(numberList, noDuplicates), 0, 10000);

        System.out.println("Enter whole numbers (max 10, or you'll be banned for 5 duplicates in 2 minutes):");

        while (input.hasNextInt() && noDuplicates.get() && numberList.size() < MAX_INPUTS) {
            int num = input.nextInt();
            // Record the number and its entry time
            numberList.add(new RepeatCheckerTask.NumberWithTimestamp(num, System.currentTimeMillis()));

            if (numberList.size() == MAX_INPUTS) {
                System.out.println("Maximum number of inputs reached!");
                System.out.println("Your inputs: " + numberList.stream()
                        .map(n -> String.valueOf(n.value))
                        .collect(Collectors.joining(", ")));
                break;
            }
        }

        // Clean up resources
        timer.cancel();
        input.close();

        if (!noDuplicates.get()) {
            System.out.println("Stop! You've violated the duplicate rule.");
        }
    }
}
Key Improvements Explained
  • Proper TimerTask usage: All check logic is in the run() method, which executes every 10 seconds as intended.
  • Sliding window tracking: We record each number's timestamp, so we only count entries from the last 2 minutes (exact, not just fixed 2-minute blocks).
  • Thread-safe state: AtomicBoolean ensures the main thread and timer thread see the latest value of noDuplicates without synchronization issues.
  • Efficient counting: A HashMap counts duplicates in linear time, making the check fast even with larger lists.
  • Clean resource management: We cancel the timer and close the scanner when done, so no background threads linger.
  • No static variables: All state is instance-specific or passed explicitly, avoiding shared state bugs.
Bonus Optimization Tip

For more flexible scheduling (and better reliability than Timer), consider using ScheduledExecutorService instead. It uses a thread pool and handles edge cases like long-running tasks better:

import java.util.concurrent.Executors;
import java.util.concurrent.ScheduledExecutorService;
import java.util.concurrent.TimeUnit;

// Replace the Timer code in main with this:
ScheduledExecutorService scheduler = Executors.newSingleThreadScheduledExecutor();
scheduler.scheduleAtFixedRate(new RepeatCheckerTask(numberList, noDuplicates), 0, 10, TimeUnit.SECONDS);

// Then clean up with:
scheduler.shutdown();

内容的提问来源于stack exchange,提问作者Ulrich Batanado

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.08 20:12:28