美文网首页
System.currentTimeMillis() 和 Sys

System.currentTimeMillis() 和 Sys

作者: 码农突围 | 来源:发表于2022-07-01 17:56 被阅读0次

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

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

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

    Windows:

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

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

    Linux:

    在 Linux 下,两者的执行耗时相差不大,不论是单线程还是多线程。

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

    如今的云主机主要有 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。

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

    相关文章

      网友评论

          本文标题:System.currentTimeMillis() 和 Sys

          本文链接:https://www.haomeiwen.com/subject/nkncbrtx.html