system.currenttimemillis,systemcurrenttimemillis多少位
java中的system.currenttimemillis()是什么东西?
System.currentTimeMillis() 获得的是自1970-1-01 00:00:00.000 到当前时刻的时间距离,类型为long
java System.currentTimeMillis()时间获取问题
System.currentTimeMillis() 返回的是 UTC 时间,你需要在此基础上加8小时就是对了。
System.currentTimeMillis() uptimeMillis() elapsedRealtime() 区别
System.currentTimeMillis() 系统时间,也就是日期时间,可以被系统设置修改,然后值就会发生跳变。
uptimeMillis 自开机后,经过的时间,不包括深度睡眠的时间
elapsedRealtime自开机后,经过的时间,包括深度睡眠的时间
所以System.currentTimeMillis()不适合计算时间间隔,eg,
now = System.currentTimeMillis()
//do something...
duration = System.currentTimeMillis() -now;
如果在do something的时候,改变了系统时间,那么 获取duration就不准了。通常在比较小的时间里,(毫秒级,秒级)一般不会有什么问题,系统时间可能不会改变。但是如果时间很长的话,那就保证不了了
uptimeMillis由于不计算睡眠时间,所以非常适合做一些特殊的时间间隔计算
elapsedRealtime 包括睡眠时间,适用于任何情况下的时间间隔计算
system.currenttimemillis()会抛出异常吗
System.currentTimeMillis()是极其常用的基础Java API,广泛地用来获取时间戳或测量代码执行时长等,在我们的印象中应该快如闪电。
但实际上在并发调用或者特别频繁调用它的情况下(比如一个业务繁忙的接口,或者吞吐量大的需要取得时间戳的流式程序),其性能表现会令人大跌眼镜。
直接看下面的Demo:
public?class?CurrentTimeMillisPerfDemo?{
????private?static?final?int?COUNT?=?100;
????public?static?void?main(String[]?args)?throws?Exception?{
????????long?beginTime?=?System.nanoTime();
????????for?(int?i?=?0;?i??COUNT;?i++)?{
????????????System.currentTimeMillis();
????????}
????????long?elapsedTime?=?System.nanoTime()?-?beginTime;
????????System.out.println("100?System.currentTimeMillis()?serial?calls:?"?+?elapsedTime?+?"?ns");
????????CountDownLatch?startLatch?=?new?CountDownLatch(1);
????????CountDownLatch?endLatch?=?new?CountDownLatch(COUNT);
????????for?(int?i?=?0;?i??COUNT;?i++)?{
????????????new?Thread(()?-?{
????????????????try?{
????????????????????startLatch.await();
????????????????????System.currentTimeMillis();
????????????????}?catch?(InterruptedException?e)?{
????????????????????e.printStackTrace();
????????????????}?finally?{
????????????????????endLatch.countDown();
????????????????}
????????????}).start();
????????}
????????beginTime?=?System.nanoTime();
????????startLatch.countDown();
????????endLatch.await();
????????elapsedTime?=?System.nanoTime()?-?beginTime;
????????System.out.println("100?System.currentTimeMillis()?parallel?calls:?"?+?elapsedTime?+?"?ns");
????}
}
执行结果如下图。
可见,并发调用System.currentTimeMillis()一百次,耗费的时间是单线程调用一百次的250倍。
如果单线程的调用频次增加(比如达到每毫秒数次的地步),也会观察到类似的情况。关注公众号Java技术栈可以获取 JVM 和多线程及更多面试题及答案。
实际上在极端情况下,System.currentTimeMillis()的耗时甚至会比创建一个简单的对象实例还要多,看官可以自行将上面线程中的语句换成newHashMap之类的试试看。
为什么会这样呢?
来到HotSpot源码的hotspot/src/os/linux/vm/os_linux.cpp文件中,有一个javaTimeMillis()方法,这就是System.currentTimeMillis()的native实现。
jlong?os::javaTimeMillis()?{
??timeval?time;
??int?status?=?gettimeofday(time,?NULL);
??assert(status?!=?-1,?"linux?error");
??return?jlong(time.tv_sec)?*?1000??+??jlong(time.tv_usec?/?1000);
}
简单来讲就是:
调用gettimeofday()需要从用户态切换到内核态;
gettimeofday()的表现受Linux系统的计时器(时钟源)影响,在HPET计时器下性能尤其差;
系统只有一个全局时钟源,高并发或频繁访问会造成严重的争用。
HPET计时器性能较差的原因是会将所有对时间戳的请求串行执行。TSC计时器性能较好,因为有专用的寄存器来保存时间戳。缺点是可能不稳定,因为它是纯硬件的计时器,频率可变(与处理器的CLK信号有关)。
关于HPET和TSC的细节可以参见:
另外,可以用以下的命令查看和修改时钟源。
~?cat?/sys/devices/system/clocksource/clocksource0/available_clocksource
tsc?hpet?acpi_pm
~?cat?/sys/devices/system/clocksource/clocksource0/current_clocksource
tsc
~?echo?'hpet'??/sys/devices/system/clocksource/clocksource0/current_clocksource
如何解决这个问题?
最常见的办法是用单个调度线程来按毫秒更新时间戳,相当于维护一个全局缓存。其他线程取时间戳时相当于从内存取,不会再造成时钟资源的争用,代价就是牺牲了一些精确度。
具体代码如下:
public?class?CurrentTimeMillisClock?{
????private?volatile?long?now;
????private?CurrentTimeMillisClock()?{
????????this.now?=?System.currentTimeMillis();
????????scheduleTick();
????}
????private?void?scheduleTick()?{
????????new?ScheduledThreadPoolExecutor(1,?runnable?-?{
????????????Thread?thread?=?new?Thread(runnable,?"current-time-millis");
????????????thread.setDaemon(true);
????????????return?thread;
????????}).scheduleAtFixedRate(()?-?{
????????????now?=?System.currentTimeMillis();
????????},?1,?1,?TimeUnit.MILLISECONDS);
????}
????public?long?now()?{
????????return?now;
????}
????
????public?static?CurrentTimeMillisClock?getInstance()?{
????????return?SingletonHolder.INSTANCE;
????}
????private?static?class?SingletonHolder?{
????????private?static?final?CurrentTimeMillisClock?INSTANCE?=?new?CurrentTimeMillisClock();
????}
}
使用的时候,直接CurrentTimeMillisClock.getInstance().now()就可以了。
不过,在System.currentTimeMillis()的效率没有影响程序整体的效率时,就不必忙着做优化,这只是为极端情况准备的。
System.currentTimeMillis与时区设置是否有关系
存在关系,这个方法是根据你当前系统的时间来的,如果你的电脑时间人为改变,它结果也会变化。
如何转换的System.currentTimeMillis;到秒
System类代表系统,系统级的很多属性和控制方法都放置在该类的内部。该类位于java.lang包。
currentTimeMillis方法
public static long currentTimeMillis()
该方法的作用是返回当前的计算机时间,时间的表达格式为当前计算机时间和GMT时间(格林威治时间)1970年1月1号0时0分0秒所差的毫秒数。
可以直接把这个方法强制转换成date类型。
代码如下:
long currentTime = System.currentTimeMillis();
SimpleDateFormat formatter = new SimpleDateFormat("yyyy年-MM月dd日-HH时mm分ss秒");
Date date = new Date(currentTime);
System.out.println(formatter.format(date));
运行结果如下:
当前时间:2011年-08月10日-14时11分46秒
另:
可获得当前的系统和用户属性:
String osName = System.getProperty(“os.name”);
String user = System.getProperty(“user.name”);
System.out.println(“当前操作系统是:” + osName);
System.out.println(“当前用户是:” + user);
System.getProperty 这个方法可以得到很多系统的属性。