Java如何实现指定时长内持续检测条件的超时判断方法
Java 超时轮询检测方法实现
实现核心逻辑
要满足「不一次性休眠满超时时长、超时窗口内持续检测」的要求,核心是基于绝对截止时间做轮询:
- 方法入口先计算超时的绝对截止时间,采用单调时钟避免系统时间调整导致的计算误差
- 每轮循环优先检测目标事件是否触发,触发则直接返回
true - 事件未触发时计算剩余可等待时长,若剩余时长已耗尽直接返回
false - 单次等待时长取「固定检测间隔」和「剩余超时时间」的较小值,避免单次等待超出总超时限制
- 单次等待结束后立刻进入下一轮检测
完整可运行代码
import java.util.concurrent.TimeUnit; import java.util.concurrent.locks.LockSupport; public class TimeoutChecker { // 轮询检测间隔,可根据业务场景调整,默认10ms平衡检测灵敏度和CPU开销 private static final long CHECK_INTERVAL_NANOS = TimeUnit.MILLISECONDS.toNanos(10); public static boolean checkTimeOut(TimeUnit unit, long timeout) { // 参数合法性校验 if (unit == null || timeout <= 0) { return isEventTriggered(); } // 转换为纳秒计算绝对截止时间,用nanoTime单调时钟不受系统时间回拨/调整影响 long totalTimeoutNanos = unit.toNanos(timeout); long deadline = System.nanoTime() + totalTimeoutNanos; while (true) { // 每轮先检测事件状态,满足直接返回 if (isEventTriggered()) { return true; } // 计算剩余等待时间 long remainingNanos = deadline - System.nanoTime(); if (remainingNanos <= 0) { // 已超时,返回false return false; } // 单次等待取检测间隔和剩余时间的较小值,避免等待超时 long waitNanos = Math.min(CHECK_INTERVAL_NANOS, remainingNanos); LockSupport.parkNanos(waitNanos); // 若线程被中断,恢复中断标记后返回超时结果,可根据业务需求调整中断处理逻辑 if (Thread.interrupted()) { Thread.currentThread().interrupt(); return false; } } } /** * 目标事件检测逻辑,替换为实际业务判断即可 * @return 事件是否触发 */ private static boolean isEventTriggered() { // 示例逻辑占位,实际使用替换为业务判断 return false; } public static void main(String[] args) { TimeUnit testingMinutes = TimeUnit.valueOf("MINUTES"); TimeUnit testingSeconds = TimeUnit.valueOf("SECONDS"); TimeUnit testingMilli = TimeUnit.valueOf("MILLISECONDS"); checkTimeOut(testingMinutes, 1); checkTimeOut(testingSeconds, 200); checkTimeOut(testingMilli, 500); } }
关键说明
- 逻辑上完全规避了一次性休眠满总时长才检测的问题,方法进入后立刻做第一次事件检测
- 检测间隔可根据业务对实时性的要求调整:如果要求事件触发后毫秒级返回,可把间隔调小;如果对CPU开销敏感,可适当调大间隔
- 采用
LockSupport.parkNanos()做等待,比Thread.sleep()精度更高,且不会抛出受检异常,代码更简洁 - 中断逻辑遵循Java并发最佳实践,捕获中断后恢复中断标记,避免中断状态丢失
内容的提问来源于stack exchange,提问作者Ori Shalhno
相关产品推荐
相关产品推荐

