System.currentTimeMillis() 和 System.nanoTime() 哪个更快?大部分人都会答错!

Posted Java技术栈

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了System.currentTimeMillis() 和 System.nanoTime() 哪个更快?大部分人都会答错!相关的知识,希望对你有一定的参考价值。

点击关注公众号,Java干货及时送达

作者:捏造的信仰
来源:https://segmentfault.com/a/1190000041276485

推荐阅读:别再用 System.currentTimeMillis() 统计耗时了,太 Low,StopWatch 好用到爆!

Java有两个取时间戳的方法:System.currentTimeMillis()System.nanoTime(),它们的使用场景是有区别的,当前网上一些文章对于这两个方法的性能讨论存在一些片面的描述,本文希望能给出一个简单的最终答案。

System.currentTimeMillis() 存在性能问题?

答案是否定的。这两个方法性能差异取决于操作系统。

Windows:

在 Windows 下,System.currentTimeMillis()System.nanoTime() 要快很多,这是因为 Windows 系统为前者提供的只是一个缓存变量,而后者则是实时的去硬件底层获取计数。

所以如果你的生产环境是 Windows,请尽可能避免使用 System.nanoTime()

Linux:

在 Linux 下,两者的执行耗时相差不大,不论是单线程还是多线程。另外,多线程系列面试题和答案全部整理好了,微信搜索Java技术栈,在后台发送:面试,可以在线阅读。

不同的虚拟机实现会带来性能差异

如今的云主机主要有 Xen 和 KVM 两种实现方式,网上有文章发现它们在取系统时间方面存在性能差异。

当你的虚拟机用的是 Xen 时,取时间的耗时会是 KVM 的十倍以上。不过上文也提供了遇到此类问题该如何解决的方案。

需要写一个专门的类来提升 System.currentTimeMillis() 性能吗?

不需要。那属于画蛇添足。

我的测试代码

我的测试代码如下,没有任何依赖,可以直接用 javac 编译然后运行。读者有兴趣可以试试:

import java.util.ArrayList;
import java.util.List;
import java.util.function.Consumer;

public class TimePerformance 

    public static final int LOOP_COUNT = 9999999;
    public static final int THREAD_COUNT = 30;

    public static void main(String[] args) 

        Runnable millisTest = () -> 

            long start = System.currentTimeMillis();
            for (int i = 0; i < LOOP_COUNT; i++) 
                System.currentTimeMillis();
            
            long end = System.currentTimeMillis();

            System.out.printf("%s : %f ns per call\\n",
                    Thread.currentThread().getName(), ((double)end - start) * 1000000 / LOOP_COUNT);
        ;

        Runnable nanoTest = () -> 

            long start = System.currentTimeMillis();
            for (int i = 0; i < LOOP_COUNT; i++) 
                System.nanoTime();
            
            long end = System.currentTimeMillis();

            System.out.printf("%s : %f ns per call\\n",
                    Thread.currentThread().getName(), ((double)end - start) * 1000000 / LOOP_COUNT);
        ;

        Consumer<Runnable> testing = test -> 
            System.out.println("Single thread test:");
            test.run();

            System.out.println(THREAD_COUNT + " threads test:");
            List<Thread> threads = new ArrayList<>();
            for (int i = 0; i < THREAD_COUNT; i++) 
                Thread t = new Thread(test);
                t.start();
                threads.add(t);
            
            // Wait for all threads to finish
            threads.forEach(thread -> 
                try 
                    thread.join();
                 catch (InterruptedException e) 
                    e.printStackTrace();
                
            );
        ;

        System.out.println(" Test System.nanoTime()");
        testing.accept(nanoTest);
        System.out.println(" Test System.currentTimeMillis()");
        testing.accept(millisTest);
    

因为我用的是 Windows,所以执行输出当中 System.nanoTime() 明显非常慢。

具体输出内容我就不放出来了,因为不具有参考价值,大多数生产环境用的是 Linux。


Spring Boot 定时任务开启后,怎么自动停止?

Java 8 排序的 10 个姿势,太秀了吧!

23 种设计模式实战(很全)

Spring Boot 保护敏感配置的 4 种方法!

面了个 5 年 Java,两个线程数据交换都不会

阿里为什么推荐使用 LongAdder?

新来一个技术总监:禁止戴耳机写代码。。

别用 System... 计时了,StopWatch 好用到爆!

Java 18 正式发布,finalize 被弃用。

Spring Boot Admin 横空出世!

Spring Boot 学习笔记,这个太全了!

关注Java技术栈看更多干货

获取 Spring Boot 实战笔记!

以上是关于System.currentTimeMillis() 和 System.nanoTime() 哪个更快?大部分人都会答错!的主要内容,如果未能解决你的问题,请参考以下文章

System.currentTimeMillis() 是不是返回 UTC 时间?

给定日期的 System.currentTimeMillis()? [复制]

System.nanoTime()和System.currentTimeMillis()性能问题

System.currentTimeMillis()

System.currentTimeMillis() uptimeMillis() elapsedRealtime() 区别

System.currentTimeMillis()和new Date().getTime()比较