一、方法定义

public static long currentTimeMillis()
  • 所属类java.lang.System
  • 返回类型long
  • 访问修饰符public static
  • 是否抛出异常:否

该方法是静态方法,无需创建对象即可调用。


二、功能说明

System.currentTimeMillis() 返回当前时间与 UTC 时间 1970年1月1日 00:00:00 之间的毫秒数(即 Unix 时间戳的毫秒形式)。

关键点:

  • 基于 协调世界时(UTC),不受本地时区影响(但显示时会受时区影响)。
  • 精度为 毫秒级(1/1000 秒)。
  • 用于测量时间间隔、生成时间戳、简单计时等。
  • 从 Java 1.0 开始支持,是最早的时间 API 之一。

⚠️ 不保证绝对准确,受系统时钟调整(如 NTP 同步)影响。


三、示例代码

1. 获取当前时间戳

long timestamp = System.currentTimeMillis();
System.out.println("当前时间戳(毫秒):" + timestamp);
// 示例输出:1722958765123

2. 计算代码执行时间

long start = System.currentTimeMillis();

// 模拟耗时操作
for (int i = 0; i < 1000000; i++) {
    Math.sqrt(i);
}

long end = System.currentTimeMillis();
System.out.println("执行耗时:" + (end - start) + " 毫秒");

3. 转换为可读时间(配合 DateSimpleDateFormat

import java.text.SimpleDateFormat;
import java.util.Date;

long now = System.currentTimeMillis();
Date date = new Date(now);
SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
System.out.println("当前时间:" + sdf.format(date));

4. 生成唯一 ID(简单场景)

String uniqueId = System.currentTimeMillis() + "-" + Thread.currentThread().getId();
System.out.println("简单唯一ID:" + uniqueId);

四、使用技巧

1. 高频计时建议使用 System.nanoTime()

// 更精确的纳秒级计时(适合微基准测试)
long start = System.nanoTime();
// ... 操作 ...
long durationNs = System.nanoTime() - start;
double durationMs = durationNs / 1_000_000.0;

currentTimeMillis() 精度低,不适合测量 < 10ms 的操作。

2. 时间比较与超时判断

long startTime = System.currentTimeMillis();
long timeout = 5000; // 5秒超时

while (System.currentTimeMillis() - startTime < timeout) {
    // 执行任务
    if (taskDone()) break;
    Thread.sleep(100);
}

3. 缓存时间戳避免重复调用

// ❌ 错误:多次调用导致时间不一致
if (System.currentTimeMillis() > threshold1 &&
    System.currentTimeMillis() < threshold2) { ... }

// ✅ 正确:缓存时间
long now = System.currentTimeMillis();
if (now > threshold1 && now < threshold2) { ... }

五、常见错误

错误 说明 修复
误认为绝对精确 受系统时钟漂移、NTP 调整影响 不用于高精度同步
用于测量短时间间隔 毫秒级精度,可能为 0 改用 System.nanoTime()
忽略时区转换 直接打印时间戳无意义 配合 Date/SimpleDateFormatjava.time 转换
用作唯一 ID 风险 同一毫秒内可能重复 加随机数或序列号:timestamp + "-" + counter

六、注意事项

  1. 不是实时时钟:返回的是系统时钟,若用户手动修改系统时间,结果会跳变。
  2. 单调性不保证:可能因 NTP 同步出现“时间回拨”(time warp)。
  3. 精度限制:大多数操作系统精度为 10~16ms,不适合微秒/纳秒级测量。
  4. 线程安全:方法本身线程安全,但用于多线程计时时需注意共享变量。
  5. 未来趋势:Java 8+ 推荐使用 java.time 包(如 Instant.now().toEpochMilli())。

七、最佳实践

推荐做法

  • 用于粗略计时(>10ms 操作)。
  • 获取当前时间戳用于日志记录、缓存过期判断。
  • Date 配合显示可读时间。
  • 在非高精度场景下生成时间相关 ID。
  • 优先使用 java.time.Instant(Java 8+)替代。

避免做法

  • 用于高精度性能分析。
  • 作为分布式系统唯一 ID 主键。
  • 依赖其单调递增性(如事件排序)。
  • 在多线程中频繁调用且不做同步。

八、性能优化建议

优化点 说明
✅ 调用开销极低 currentTimeMillis() 是本地方法,调用非常快
✅ 无需缓存(单次) 单次调用无需优化
⚠️ 高频调用注意 若每秒调用数万次,可考虑缓存最近时间(如“时间轮”)
✅ 优先使用 nanoTime() 测性能 更适合基准测试
✅ 使用 java.time 替代旧 API 更现代、更安全

示例:缓存时间(高频场景)

public class CachedTime {
    private static volatile long currentTimeMillis = System.currentTimeMillis();

    public static void update() {
        currentTimeMillis = System.currentTimeMillis();
    }

    public static long now() {
        return currentTimeMillis;
    }

    // 后台线程每10ms更新一次
}

适用于日志时间戳等高频但精度要求不高的场景。


九、与现代时间 API 对比(Java 8+)

方法 优点 推荐场景
System.currentTimeMillis() 简单、兼容老版本 兼容性要求高、简单计时
Instant.now().toEpochMilli() 属于 java.time,不可变、线程安全 Java 8+ 项目推荐
System.nanoTime() 高精度、单调递增 性能测量、延迟计算

推荐写法(Java 8+):

// ✅ 推荐:使用 java.time
long timestamp = Instant.now().toEpochMilli();

// ✅ 高精度计时
long start = System.nanoTime();
// ...

十、总结

项目 要点
本质 返回自 1970-01-01T00:00:00Z 起的毫秒数
用途 获取时间戳、简单计时、日志记录
精度 毫秒级,受系统时钟影响
优势 简单、高效、广泛支持
局限 精度低、非单调、不推荐用于高精度场景
替代方案 Instant.now()(Java 8+)、System.nanoTime()(计时)
关键建议 计时用 nanoTime,时间戳用 Instant,老项目可用 currentTimeMillis

一句话总结
System.currentTimeMillis() 是 Java 最基础的时间获取方法,适合简单场景和兼容老代码,但在 Java 8+ 环境中,应优先使用 java.time.Instant 获取时间戳,使用 System.nanoTime() 进行高精度计时。