[TOC]

文章参考:https://www.cnblogs.com/andy-songwei/p/10784049.html

文章参考:https://www.codenong.com/cs106221500/

概述

JDK提供了两个方法,System.currentTimeMillis()和System.nanoTime(),这两个方法都可以用来获取表征当前时间的数值。但是如果不仔细辨别这两个方法的差别和联系,在使用当中也很容易出错。笔者在前不久的工作当中使用System.currentTimeMillis()时就踩了一个大坑,后来在查明System.currentTimeMillis()和System.nanoTime()的特性后,才用System.nanoTime()来填了这个坑。本文,笔者就以自己的踩坑和填坑经历来介绍一下这两个方法。

文章的开头,笔者先描述一下自己前不久工作当中碰到的一个bug,分析过程以及解决办法。

1、问题描述

​ 当手机按power键亮屏时,会调用人脸解锁功能来解锁手机。如果高频率不停地按power键,人脸解锁功能会被不停地调用,这样会产生很多并发问题,导致一些不可预料的异常,同时在这么高频率下,也没有必要每次亮屏都调用人脸解锁功能,需要过滤掉其中一部分调用。当时的处理办法是,当上一次调用人脸解锁功能的时候记录当前时间点 long mLastUnlockTime = System.currentTimeMillis(); 当再次调用的时候,也记录当前时间点 long nowUnlockTime = System.currentTimeMillis()。然后判断这两者的时间差 long durTime = nowUnlockTime - mLastUnlockTime,如果durTime<=300,表示距离上次调用不到300毫秒,本次不允许继续调用;如果durTime>300,表示距离上一次调用已经超过300毫秒了,则允许这一次继续调用,并把nowUnlockTime 的值赋给mLastUnlockTime,用于进行下一次的判断。

​ 按照这个思路,就是防止300毫秒内连续调用两次人脸解锁功能,这种设计看起来似乎没什么问题。但是这个设计在正常运行了几个月后,测试人员提了一个bug:如果在系统设置中把时间往回调,那么人脸解锁功能就失效了。

当收到这个bug后,我百思不得其解,调个系统时间能把人脸解锁功能给调失效了?我一度觉得这个现象很奇葩,不过作为一名老猿,我当然是去关键部分添加log分析原因了,最终定位到,是durTime出现问题了,居然出现了负数!!!这个时间差怎么会出现负数呢?仔细分析后才发现,这是System.currentTimeMills()的特性所致:该方法记录的是系统时间距离1970年1月1日的毫秒数。当把时间往前调了,本次获取的时间点nowUnlockTime 当然就小于上一次记录的时间值了,那自然而然 durTime 就是负数了。

后来和某同事聊天,说起了这个听起来似乎挺奇葩的现象,同事说推荐我去了解一下System.namoTime()这个方法。后来用 System.namoTime() 取代 System.currentTimeMillis() 后,问题就迎刃而解了。