使用system.currenttimemillis()做间隔判断需记录上一次时间戳并比较差值,虽简单轻量但受系统时钟跳变影响,应添加now
用
System.currentTimeMillis()做间隔判断,核心是记录上一次操作的时间戳,再和当前时间比较差值是否超过阈值。它简单、轻量、无需额外依赖,适合大多数基础场景,但要注意精度、时钟漂移和线程安全等细节。记录与比较:最简间隔控制
每次操作前保存当前时间戳,下次触发时计算差值:
- 定义一个
long lastTime = 0字段(成员变量或静态变量)- 操作开始前获取当前时间:
long now = System.currentTimeMillis()- 判断是否满足间隔条件:
if (now - lastTime >= 5000) { /* 允许执行 */ lastTime = now; }例如限制按钮点击间隔 5 秒,就用这个逻辑避免频繁提交。
注意系统时钟跳变带来的误判
currentTimeMillis()依赖系统时钟,若用户手动调时间或 NTP 同步导致时间回拨/突进,now - lastTime可能为负或异常大,造成逻辑失效。
- 可加防护:若
now ,视为时钟异常,重置 <code>lastTime或跳过判断- 对强一致性要求高的场景(如防重放、令牌刷新),建议改用
System.nanoTime()配合单调递增逻辑,或引入 Redis 等外部时序存储多线程下需保证更新原子性
多个线程共用同一个
lastTime变量时,读-改-写存在竞态风险,可能导致间隔被绕过。
- 简单方案:用
volatile long lastTime+AtomicLong.compareAndSet()替代直接赋值- 更稳妥做法:用
synchronized块包裹判断和更新逻辑- 高频并发场景建议结合令牌桶或滑动窗口算法,而非仅靠时间戳
替代方案:考虑更语义化的工具类
单纯靠时间戳易出错,JDK 和常用库提供了更高层的抽象:
ScheduledExecutorService:适合周期性任务调度,自带延迟/间隔控制RateLimiter(Guava):基于令牌桶,支持平滑限流,自动处理时间漂移StopWatch(Apache Commons Lang):封装了开始/停止/校验逻辑,代码更可读业务逻辑简单时用
currentTimeMillis()完全够用;一旦涉及精度、并发或复杂策略,建议升级到专用组件。












