android时间戳总结:System.nanoTime(),System.currentTimeMillis(),SystemClock

本文详细介绍了在Android开发中四种时间戳的使用方法及其差异,包括System.nanoTime(), System.currentTimeMillis(), SystemClock.uptimeMillis() 和 SystemClock.elapsedRealtime()。探讨了它们在不同场景下的适用性和精度,如系统启动时间、系统时钟日期计算及线程运行时间等。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

今天的主题,从头到尾就两个字:时间。

坚持看完整篇blog,一定会有收获。

开发中经常要用到时间戳,下面将会详细介绍,如下系统函数的功能和差异 :

  • System.nanoTime()
  • System.currentTimeMillis()
  • SystemClock.uptimeMillis()
  • SystemClock.elapsedRealtime()
  • SystemClock.currentThreadTimeMillis

0、时间的单位:

秒:second

毫秒:Millisecond

微妙:Microsecond

纳秒:nanosecond

1秒 = 1000毫秒;1毫秒=1000微秒, 1微秒=1000纳秒,

注意:【纳秒的单位千万别弄错了,马上我们就会用到这个单位】

1毫秒 = 1000 000纳秒;一百万纳秒

1毫秒 = 1000 000纳秒;一百万纳秒

1毫秒 = 1000 000纳秒;一百万纳秒

一 、System.nanoTime()

单位:纳秒

android系统开机到当前的时间

系统设置修改时钟,不影响该时间。

重启android系统后该值会重置为0。

二、System.currentTimeMillis()

单位:毫秒(milliseconds)

从1970.1.1 UTC 零点开始到当前的时间

修改系统时钟,会直接修改该时间。可以通过该值推算当前系统时钟的日期和时间。

重启手机对该时间无影响。

三、System.nanoTime()有什么用呢?

System.nanoTime:返回的时间单位是纳秒,他是毫秒的百万分之一。远比毫秒的颗粒度要低。

如下情况,使用,System.currentTimeMillis,计算不出时间差,但是System.nanoTime可以:

public class TimeStampMain {

    public static void main(String[] args) {
        long milliTimeBegin = System.currentTimeMillis();
        long nanoTimeBegin = System.nanoTime();
        for (int i = 0; i < 200; i++){

        }
        long nanoDuration = System.nanoTime() - nanoTimeBegin;
        long milliDuration = System.currentTimeMillis() - milliTimeBegin;

        System.out.println("循环100次消耗的时间:nanoDuration=" + nanoDuration + "纳秒, milliDuration=" + milliDuration + "毫秒");
    }
}

日志1

四、SystemClock

/**

 * milliseconds of non-sleep uptime since boot.

 * 单位:毫秒
 * 系统重启后将重0开始计算,android系统进入深度睡眠后将会暂停计时
 
**/

long uptimeMillis();



/**

 * Returns milliseconds since boot, including time spent in sleep.

 * 单位:毫秒
 * 系统重启后将重新开始计算,android系统进入深度睡眠,不会停止计时。

*/

long elapsedRealtime();



/**

 * Returns milliseconds running in the current thread.

 * 单位:毫秒
 * 线程running的时间,线程Sleep的时间不会计入。
 * 

**/

long currentThreadTimeMillis();


SystemClock.currentThreadTimeMillis()

注意currentThreadTimeMillis()返回的是当前线程running的时间,注意是running的时间。我们通过如下例子来理解什么叫着running的时间。并且单位是毫秒。

new Thread(){

  @Override

  public void run() {

    try {
      Log.w(TG, "currentThreadTimeMillis1=" + SystemClock.currentThreadTimeMillis());//日志1
      Thread.sleep(20000);//20ms
      Log.w(TG, "currentThreadTimeMillis2=" + SystemClock.currentThreadTimeMillis());//日志2
    } catch (InterruptedException e) {
      e.printStackTrace();
    }
    
  }

}.start();

你猜,日志输出currentThreadTimeMillis1=?currentThreadTimeMillis2=?





输出日志:
日志2

五、结尾

再次回到我们的主题,时间。


大叔,有一次面试“某福报厂”,面试官问了一个问题,让我陷入沉思了很久很久很久……以下是面试官的原话:

在我们公司,有着很多狠多的学霸,假如,你加入我们之后,你会发现很多来自国内外名校,智商很高的同事。他们学习能力很强。你怎么能做到不落后甚至超越他们呢?

大叔,思考了很久很久,终于找到了适合大叔的答案:时间

程序员,面对快速迭代的技术,持续学习的能力无疑是杀手锏,短时间我们学习的速度赶不上学霸,但是持之以恒的学习,一个个技术细节慢慢啃,夜以继日的啃,不敢说能赶上大部分学霸,最起码能让研发能力领先在中上水平以上。
随着时间的力量,这个领先会越来越领先。
时间可以是把杀猪刀,时间也可以是把屠龙刀。

逝者如斯夫,我相信时间的力量,坚持的力量。

积跬步,终将至千里;积小流,必成江海。

原文连接:https://juejin.im/post/5eb00f786fb9a043340bf6a8
更多android技术blog:https://juejin.im/collection/5eaff93ee51d45364b88a912









关键字:

时间戳; 开发技术如何与不落后学霸; 技术能力如何不落后; 程序员必备技能; currentTimeMillis; nanoTime; SystemClock;

<think>好的,我现在需要帮用户解决如何用Java记录代码执行时间的问题。首先,我得考虑用户可能的背景和使用场景。用户可能是一个刚开始学习Java的开发者,或者是有一定经验但想优化代码性能的人。他们的需求是测量某段代码的执行时间,以便进行性能分析或优化。 接下来,我需要回忆Java中常用的几种记录执行时间的方法。最基础的就是使用System.currentTimeMillis(),在代码块前后获取时间戳然后相减。但这种方法在计算时可能会有误差,比如系统时间被调整的情况,不过对于大多数应用来说已经足够。另外,Java 8引入了Instant和Duration类,提供了更精确的时间操作,适合需要更高精度的场景。 然后,还有System.nanoTime(),这个方法返回的是当前JVM的高精度时间源,通常用于测量时间间隔,不受系统时钟变化的影响,适合短时间的性能测试。不过用户需要注意,nanoTime在不同操作系统上的精度可能不同,比如Windows通常精度较低。 还有StopWatch类,比如Apache Commons Lang和Spring框架都提供了自己的实现。这些工具类封装了时间的计算,使用起来更方便,同时可能提供了更多的功能,比如分段时间记录等。需要提醒用户如果需要这些功能,可以引入相应的依赖。 此外,Java 9引入的新的API,比如新的日期时间API中的Clock类,但可能对于记录执行时间来说,之前的几种方法已经足够。另外,需要考虑用户是否可能使用Java Agent或者AOP(面向切面编程)来进行无侵入式的执行时间监控,这对方法级别的性能分析很有用,比如结合Spring AOP或AspectJ。 用户可能没有提到的深层需求包括:是否需要线程安全的实现,是否需要记录多个时间片段,或者是否需要将记录的时间输出到日志文件或监控系统中。例如,在Web应用中,可能需要记录每个请求的处理时间,这时候结合拦截器或过滤器使用会更高效。 另外,需要考虑不同方法的精度和开销。System.nanoTime()虽然精度高,但频繁调用可能会有性能影响。而使用第三方库如StopWatch可能带来额外的依赖,但简化了代码。需要根据具体场景做出权衡。 可能还需要提醒用户避免在代码中到处写时间记录的代码,这样会导致代码冗余,建议使用AOP或工具类进行封装,提高代码的可维护性。同时,对于生产环境,可能需要更专业的性能分析工具,如JMH(Java Microbenchmark Harness)来进行基准测试,避免手工测试的不准确性。 最后,总结常用的几种方法,并给出示例代码,帮助用户快速实现。同时提醒注意事项,比如避免在关键性能路径中频繁记录时间,选择合适的时间单位,以及处理多线程环境下的线程安全问题等。</think>在Java中记录代码执行时间主要有以下几种常用方法,按使用场景和精度要求分类: --- ### 一、基础计时方法 #### 1. System.currentTimeMillis() ```java long startTime = System.currentTimeMillis(); // 要计时的代码 long endTime = System.currentTimeMillis(); System.out.println("耗时:" + (endTime - startTime) + "ms"); ``` *适用场景*:简单计时,精度到毫秒 #### 2. System.nanoTime() ```java long start = System.nanoTime(); // 要计时的代码 long end = System.nanoTime(); System.out.println("耗时:" + (end - start)/1_000_000 + "ms"); ``` *优势*:更高精度(纳秒级),适合短时间测量 --- ### 二、Java 8+ 时间API #### 1. Instant + Duration ```java Instant start = Instant.now(); // 要计时的代码 Duration duration = Duration.between(start, Instant.now()); System.out.printf("耗时:%d毫秒%n", duration.toMillis()); ``` #### 2. Clock类(带时区) ```java Clock clock = Clock.systemUTC(); Instant start = clock.instant(); // 要计时的代码 long elapsed = clock.millis() - start.toEpochMilli(); ``` --- ### 三、第三方工具类 #### 1. Apache Commons StopWatch ```java StopWatch stopWatch = new StopWatch(); stopWatch.start(); // 代码段1 stopWatch.split(); System.out.println("分段耗时:" + stopWatch.getSplitTime()); // 代码段2 stopWatch.stop(); System.out.println("总耗时:" + stopWatch.getTime()); ``` *依赖*: ```xml <dependency> <groupId>org.apache.commons</groupId> <artifactId>commons-lang3</artifactId> <version>3.12.0</version> </dependency> ``` #### 2. Spring Framework StopWatch ```java StopWatch watch = new StopWatch("性能分析"); watch.start("模块A"); // 模块A代码 watch.stop(); watch.start("模块B"); // 模块B代码 watch.stop(); System.out.println(watch.prettyPrint()); ``` --- ### 四、高级监控方案 #### 1. 使用AOP统一记录 ```java @Aspect @Component public class TimeMonitorAspect { @Around("execution(* com.example.service.*.*(..))") public Object logTime(ProceedingJoinPoint pjp) throws Throwable { long start = System.currentTimeMillis(); Object result = pjp.proceed(); System.out.println(pjp.getSignature() + " 耗时:" + (System.currentTimeMillis() - start) + "ms"); return result; } } ``` #### 2. JMH基准测试(专业级) ```java @BenchmarkMode(Mode.AverageTime) @OutputTimeUnit(TimeUnit.MILLISECONDS) public class MyBenchmark { @Benchmark public void testMethod() { // 被测代码 } } ``` --- ### 五、生产环境最佳实践 1. **日志规范**: ```java private static final Logger logger = LoggerFactory.getLogger("PERF_LOG"); logger.debug("DB查询耗时:{}ms", duration); ``` 2. **多维度统计**: ```java long start = System.nanoTime(); try { // 业务代码 } finally { long cost = (System.nanoTime() - start)/1_000_000; Metrics.timer("api_request").record(cost, TimeUnit.MILLISECONDS); } ``` 3. **异步记录**: ```java CompletableFuture.runAsync(() -> { // 将耗时数据写入监控系统 }); ``` --- ### 注意事项: 1. **热点代码优化**:避免在循环内部频繁创建计时对象 2. **时间单位选择**: - 秒级:TimeUnit.SECONDS - 毫秒级:TimeUnit.MILLISECONDS - 纳秒级:TimeUnit.NANOSECONDS 3. **线程安全**:多线程环境使用ThreadLocal 4. **异常处理**:在finally块中确保时间记录 ```java long start = System.currentTimeMillis(); try { // 可能抛出异常的代码 } finally { long cost = System.currentTimeMillis() - start; } ``` --- 根据实际需求选择方案: - 快速调试:System.currentTimeMillis() - 方法级监控:AOP + 日志 - 性能基准测试:JMH - 生产监控:Metrics + Prometheus/Grafana
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值