System.currentTimeMillis()与elapsedRealtime()区别

System.currentTimeMillis()SystemClock.elapsedRealtime() 在 Android 开发中用于不同的时间测量场景,核心区别在于它们的底层实现和对系统时间变化的敏感度。以下是详细说明和代码示例:


1. System.currentTimeMillis()

  • 定义:返回自 1970 年 1 月 1 日 UTC 以来的毫秒数(Unix 时间戳)。
  • 特点
    • 受系统时间设置影响(用户或网络时间同步可能导致时间跳变)。
    • 设备休眠时不会递增。
  • 适用场景:需要与真实时间相关的操作,如记录事件时间、生成日期字符串等。

代码示例:记录事件时间戳

java 复制代码
// 记录用户点击事件的时间
long clickTime = System.currentTimeMillis();
saveToDatabase("User clicked at " + clickTime);

// 将时间戳转换为可读日期
SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss", Locale.getDefault());
String dateStr = sdf.format(new Date(clickTime));
Log.d("EventTime", "点击时间: " + dateStr);

2. SystemClock.elapsedRealtime()

  • 定义:返回自设备启动以来经过的毫秒数(包括深度休眠时间)。
  • 特点
    • 不受系统时间设置影响。
    • 设备休眠时仍会累计时间。
  • 适用场景:测量时间间隔(如性能统计、倒计时),需稳定不受系统时间干扰的场景。

代码示例:测量代码执行时间

java 复制代码
// 开始计时
long startTime = SystemClock.elapsedRealtime();

// 模拟耗时操作(如下载文件)
new Thread(() -> {
    try {
        Thread.sleep(2000); // 模拟 2 秒操作
    } catch (InterruptedException e) {
        e.printStackTrace();
    }

    // 计算实际耗时
    long endTime = SystemClock.elapsedRealtime();
    long duration = endTime - startTime;
    Log.d("Performance", "操作耗时: " + duration + " 毫秒");
}).start();

错误用法示例

错误:使用 System.currentTimeMillis() 计算耗时

java 复制代码
long start = System.currentTimeMillis();
// 假设用户在此期间调整了系统时间
Thread.sleep(5000); // 实际耗时 5 秒
long end = System.currentTimeMillis();
long wrongDuration = end - start; // 可能得到负数或极大值

正确:使用 SystemClock.elapsedRealtime()

java 复制代码
long start = SystemClock.elapsedRealtime();
Thread.sleep(5000);
long end = SystemClock.elapsedRealtime();
long correctDuration = end - start; // 始终准确为 ~5000 毫秒

总结对比表

特性 System.currentTimeMillis() SystemClock.elapsedRealtime()
时间基准 Unix 时间戳(1970 年) 设备启动后经过的时间
系统时间敏感 ✔️(用户修改时间会影响结果) ❌(结果稳定,不受时间设置影响)
休眠时递增 ❌(休眠时暂停) ✔️(持续计时,包括休眠)
典型用途 日历事件、日志时间戳 性能统计、倒计时、间隔测量

高级场景:跨进程时间同步

在需要跨组件(如 ServiceActivity)同步时间的场景中,elapsedRealtime() 更可靠。例如,音乐播放器显示播放进度:

java 复制代码
// Service 中记录播放开始时间
long playbackStartTime = SystemClock.elapsedRealtime();

// Activity 中实时计算已播放时长
long currentElapsed = SystemClock.elapsedRealtime();
long playbackDuration = currentElapsed - playbackStartTime;
updateUI("已播放: " + playbackDuration + " 毫秒");

通过理解两者的差异,可以在不同场景中选择合适的 API 确保时间逻辑的准确性。

相关推荐
HLC++8 小时前
Linux的进程间通信
android·linux·服务器
爱笑鱼12 小时前
Binder(二):AIDL 生成的 Proxy、Stub 和 Parcel 到底在做什么?
android
爱笑鱼12 小时前
Binder(一):一次方法调用,究竟怎样跨进程执行?
android
壮哥_icon13 小时前
【Android 系统开发】使用 BAT 脚本高效自动化管理 /system/priv-app/ 系统应用(安装与卸载)
android·运维·自动化
用户693717500138414 小时前
Claude Code终端日志Token占用实测:一个过滤器砍掉60%-90%
android·前端·后端
蝉蜕日记15 小时前
AccumuPDF高级版 v2.57 | 视图文转换PDF,合并分割压缩
android·智能手机·pdf·生活·软件需求
吐了啊取名字太难15 小时前
美颜系统AI修图本地跑并支持Mac、win、安卓、iOS不卡顿
android·人工智能·windows·数码相机·mac·ai编程
阿pin16 小时前
Android随笔-Retrofit
android·retrofit
想取一个与众不同的名字好难16 小时前
安卓自定义颜色选择器
android
我命由我1234517 小时前
Android 开发问题:java.lang.NoSuchMethodError:No virtual method readAllBytes()
android·java·java-ee·kotlin·android studio·android-studio·android runtime