1、问题
java 中,new Date() 方法,获取的时间,究竟与当前的系统时间有什么关联?简单的时刻对应关系吗?
2、测试环境
版本:jdk1.8.0_131
主方法: public static void main(String[] args) throws InterruptedException {
SimpleDateFormat dateFormat = new SimpleDateFormat("HH:mm:ss");
int i = 0;
while(true){
System.out.println(i + "\t" +dateFormat.format( new Date() ) );
i++;
Thread.sleep(2000);
}
}
3、更新时间前
如上图所示,控制台输出的时间,与当前的系统时间一致。
4、更新时间后
保持该main方法一直在运行(不中断,一直在死循环中), 利用win10下的时间设置,更改系统时间后
如上图所示,控制台输出的时间,依然以更新时间前的为基准进行输出。
5、代码溯源
Date.java
package java.util;
public class Date
/**
* Allocates a Date
object and initializes it so that
* it represents the time at which it was allocated, measured to the
* nearest millisecond.
*
* @see java.lang.System#currentTimeMillis()
*/
public Date() {
this(System.currentTimeMillis());
}
}
System.java
package java.lang;
public final class System {
/**
* Returns the current time in milliseconds. Note that
* while the unit of time of the return value is a millisecond,
* the granularity of the value depends on the underlying
* operating system and may be larger. For example, many
* operating systems measure time in units of tens of
* milliseconds.
*
*
See the description of the class Date
for
* a discussion of slight discrepancies that may arise between
* "computer time" and coordinated universal time (UTC).
*
* @return the difference, measured in milliseconds, between
* the current time and midnight, January 1, 1970 UTC.
* @see java.util.Date
*/
public static native long currentTimeMillis();
}
6、分析
现象:JVM 在某一时刻,获取当前系统时间,同时内部维护该时间(或者说时刻更为准确),后续所有的时间操作,均以此时刻为基准。
由于不确定该时刻是JVM启动时,还是调用 new Date() 方法时;同时为了排除SimpleDateFormat相关方法故继续测试。
7、 继续测试1
更新测试主方法:
要点:确定该时刻,同时排除SimpleDateFormat相关方法影响
public static void main(String[] args) throws InterruptedException {
int i = 0;
System.out.println("开始---" );
Thread.sleep(10000);
System.out.println("正式输出---" );
while(true){
System.out.println(i + "\t" + new Date() );
i++;
Thread.sleep(2000);
}
}
说明:在Thread.sleep(10000) ,利用这段时间(10秒),更新系统时间
如上图,更新系统时间前,JVM进程已经启动。
如上图,利用这段时间(10秒),更新系统时间,此时,控制台输出的时间,以更新后的时间为基准进行输出。
8、继续测试2
现象:确定不是在 JVM启动时,内部维护该时刻。
但是依然不确定该时刻是调用 new Date() 方法时,还是调用 **System.currentTimeMillis()**时(参见 5、代码溯源 部分 ),故继续测试。
更新测试主方法:
要点:在调用new Date()前,先行调用System.currentTimeMillis() 方法。 public static void main(String[] args) throws InterruptedException {
int i = 0;
System.out.println("开始---" );
System.out.println("当前系统时间对应的毫秒数:" + System.currentTimeMillis());
Thread.sleep(10000);
System.out.println("正式输出---" );
while(true){
System.out.println(i + "\t" + new Date() );
i++;
Thread.sleep(2000);
}
}
测试方法同上一部分,即:
利用这段时间(10秒),更新系统时间.
现象:该时刻不以调用 System.currentTimeMillis() 时为基准。
9、 分析
System.currentTimeMillis()产生一个当前的毫秒,这个毫秒其实就是自1970年1月1日0时起的毫秒数,Date()其实就是相当于Date(System.currentTimeMillis()); 因为Date类还有构造Date(long date),用来计算long秒与1970年1月1日之间的毫秒差。得到了这个毫秒数,我们自己也可以算起现在的年月日周时
10、猜想
new Date()第一次执行时,获取当前系统时间,同时内部维护该时间(或者说时刻更为准确),后续所有的时间操作,均以此时刻为基准。
继续查阅Date.java 方法
private transient long fastTime;
public Date() {
this(System.currentTimeMillis());
}
public Date(long date) {
fastTime = date;
}