System.nanoTime() 是 Java 中 java.lang.System 类提供的静态方法,核心作用是获取高精度的相对时间戳,专门用于测量极短的时间间隔(如微秒/纳秒级),而非获取绝对的日期时间。
1. 核心定义与基础特性
1.1. 方法签名
public static long nanoTime()返回值是 long 类型,单位为纳秒(1纳秒 = 10⁻⁹秒,1毫秒 = 10⁶纳秒)。
1.2. 核心逻辑
- 该方法返回的是 JVM 进程内的相对时间:时间起点不是固定的(既不是 1970-01-01 00:00:00,也不是系统启动时间),而是 JVM 实例启动后某个底层系统的“高分辨率时间源”的起始点。
- 返回值本身无绝对时间意义(无法转换为具体日期),仅能通过“结束值 - 起始值”计算时间间隔。
1.3. 精度与稳定性
- 标称精度:纳秒级,但实际精度依赖操作系统和硬件(比如 Windows 通常约 100 纳秒,Linux/macOS 可达 1 纳秒);
- 稳定性:不受系统时钟调整(如手动改时间、NTP 同步、夏令时)影响,是测量短时间间隔的“黄金标准”。
2. 核心用途:测量短时间间隔
System.nanoTime() 唯一合理的用途是计算两段代码之间的执行耗时,尤其适合测量微秒/纳秒级的短任务(如算法执行、方法调用耗时)。
示例:测量代码执行耗时
public class NanoTimeDemo {
public static void main(String[] args) {
// 1. 记录起始时间
long startTime = System.nanoTime();
// 2. 待测量的代码段(示例:执行100万次平方根计算)
for (int i = 0; i < 1_000_000; i++) {
Math.sqrt(i);
}
// 3. 记录结束时间
long endTime = System.nanoTime();
// 4. 计算耗时(纳秒 → 毫秒,便于阅读)
long durationNano = endTime - startTime;
double durationMs = durationNano / 1_000_000.0; // 1毫秒=10^6纳秒
System.out.println("代码执行耗时:" + durationNano + " 纳秒");
System.out.println("代码执行耗时:" + String.format("%.3f", durationMs) + " 毫秒");
}
}输出:
代码执行耗时:5639900 纳秒
代码执行耗时:5.640 毫秒3. 与 System.currentTimeMillis() 的核心区别
很多开发者会混淆这两个方法,核心差异如下(表格更清晰):
| 特性 | System.nanoTime() | System.currentTimeMillis() |
|---|---|---|
| 时间类型 | 相对时间(仅间隔有意义) | 绝对时间(UTC 时间戳,从 1970-01-01 00:00:00 开始) |
| 单位/精度 | 纳秒级(实际精度依赖系统) | 毫秒级(精度低,仅适合秒/毫秒级间隔) |
| 受系统时钟影响 | 不受(改时间、NTP 同步不影响) | 受影响(改系统时间会导致值跳变) |
| 用途 | 测量短时间间隔(如代码耗时) | 获取当前日期时间、存储时间戳 |
| 返回值意义 | 仅差值有效,无绝对意义 | 可转换为具体日期(如 new Date(long)) |
4. 关键注意事项
禁止用于绝对时间场景: 不能用
nanoTime()存储时间戳、记录事件发生时间(比如日志的时间戳),因为不同 JVM 实例、不同机器的起始点完全不同,跨进程/机器无意义。计算间隔时用 long 接收: 虽然返回值是
long,但计算end - start时仍需确保用long存储(避免溢出,纳秒级数值很大,但long足够容纳)。精度≠准确度: “纳秒级返回值”不代表每次调用的误差是1纳秒,实际误差由操作系统的时间源精度决定(比如 Windows 下误差约 100 纳秒),但仍远优于
currentTimeMillis()。极少数值回退情况: 极端情况下(如系统切换时间源),可能出现
endTime < startTime,建议计算时做容错(比如取绝对值):javalong duration = Math.abs(endTime - startTime);
5. 总结
System.nanoTime() 是 Java 中高精度测量短时间间隔的核心方法,核心价值是“稳定、高精度”,适合算法性能测试、短任务耗时分析;而如果需要获取当前日期时间、存储时间戳,应使用 System.currentTimeMillis() 或 java.time 包(如 Instant.now())。