system.currenttimemillis()超时控制需边执行边检查耗时,起始时间早记、阈值明确配置,在循环/io前等关键点插入判断,超时后立即释放资源、跳过非核心逻辑并返回降级结果。

用 System.currentTimeMillis() 判断任务是否超时,核心就一句话:**在关键位置反复比对已耗时,一超就停、不等到底**。它不是“事后算账”,而是边跑边盯,适合同步、可控、非阻塞的业务逻辑。
起始时间要早,超时阈值要明确
任务一开始就得记下起点,别等进循环或发请求才开始计时;超时值建议设为常量或配置项,避免硬编码散落各处:
-
推荐写法:
long start = System.currentTimeMillis(); int timeoutMs = 500; - 别用
new Date().getTime()替代——两者效果一样,但currentTimeMillis()更轻量、语义更清晰 - 如果超时要求严苛(比如 ≤10ms),注意该方法精度通常在 10–15ms 级,可考虑
System.nanoTime()配合相对差值
检查点要落在“可能卡住”的地方
只在开头和结尾判断毫无意义。真正有效的是在执行路径中那些**耗时不可控、容易堆积或依赖外部响应**的位置插入检查:
- 循环体内部(尤其是遍历大量数据、解析嵌套结构时)
- HTTP 请求发起前(避免调用后无限等待)
- 数据库查询执行前,或分页 fetch 下一批结果前
- 复杂计算的中间节点(如解密一段内容、校验一个签名后)
例如:
for (String item : hugeList) {
if (System.currentTimeMillis() - start >= timeoutMs) {
log.warn("处理超时,跳过剩余 {} 条", hugeList.size() - i);
break;
}
process(item);
}超时后必须快速收尾,不能硬扛
一旦判定超时,立刻停止后续逻辑,重点做三件事:
- 释放资源:关闭未读完的 InputStream、断开未完成的 HTTP 连接、删除临时文件句柄
- 跳过非核心路径:不记录详细日志、不触发异步通知、不更新缓存
-
返回明确结果:用预设默认值、降级缓存数据,或抛出带超时标识的异常(如
throw new TimeoutException("fetch config"))
注意:超时处理路径里不要再做 I/O 或加锁,否则可能把自己拖垮。
适用场景有边界,别强套
这套方案轻量、无依赖,但不是万能的:
- ✅ 适合单线程同步流程、CPU 密集型任务、可控循环逻辑
- ❌ 不适用于真正阻塞调用(如
socket.read()、Object.wait()),它们无法被外部中断,得靠 API 自身的 timeout 参数 - ❌ 多线程共享同一
start时间戳且无同步保护时,可能因并发读写或系统时钟漂移误判











