如何衡量一个线程在java中从新到终的确切时间

时间:2016-08-04 10:19:13

标签: java java-threads

问题:

  1. 无论如何都要获得一个主题从新到结束的确切时间?
  2. 为什么每次的结果都有很大差异(见下面的代码)?
  3. 代码:

    public void process2(){
        final long start = System.currentTimeMillis();
        Thread newT = new Thread(new Runnable() {
            @Override
            public void run() {
                // long end = System.currentTimeMillis();
                // System.out.println((end-start));
    
                for (int i = 1, sum = 0; i < 1000; i++) {
                    sum += i;
                }
            }
        });
        long end1 = System.currentTimeMillis();
        System.out.println("new thread time took :" + (end1 - start));
        newT.start();
    
        int i = 0;
        while (newT.isAlive()) {
            i++;
        }
    
        long end = System.currentTimeMillis();
        System.out.println("total time:" + (end - start));
        System.out.println("judge count:" + i);
    
    }
    

2 个答案:

答案 0 :(得分:1)

  1. 衡量执行时间通常更为相关,即执行run()方法所需的时间。不同运行之间的时间通常相似。

  2. Thread对象的创建成本相当高,并且取决于系统当前可用的资源,这就是为什么在创建Thread之间可能存在很大差异的原因。它的执行。更重要的是,在破坏线程之前,还有一个清理过程也会占用大量时间。

  3. 优化线程管理时间(创建/销毁)的一种方法是使用ThreadPoolExecutorService。有关详细信息,请参阅Oracle concurrency tutorial

答案 1 :(得分:0)

你已经为测量做了一个非常糟糕的例子。

首先,使用new创建一个新线程是 dead cheap (它是一个普通的java对象)。但是你为匿名的Runnable包含了实际的类加载时间。这将涉及I / O,因此预期执行时间会有很大差异,尤其是在第一次运行时。

然后你以毫秒为单位测量时间。但是系统时间不一定具有实际的毫秒分辨率(读取System.currentTimeMillis的javadoc)。此外,您尝试测量的内容大部分时间都是在 less 中执行而不是毫秒。

你的Runnable没有可观察到的副作用,因此JIT可能只是在短暂的热身后优化整个代码。经过几次运行后,runnable实际上可能根本不需要任何时间。

您正在轮询以确定其他线程何时结束。多数民众赞成保持CPU(如果你有一个以上,那么一个核心)忙于无所事事。对于单核心机器而言,这意味着除了检查线程是否存活之外,平均花费50%的时间。根据操作系统调度程序如何运行线程,这是另一种变异来源。

总而言之,你已经制作了一个 microbenchmark ,你已经介入了微基准测试在java中可能遇到的所有最常见的陷阱。在Java中进行基准测试需要一些小心,或者您将测量任何内容,但不会测量您实际想要测量的代码的性能。有基准测试框架和关于如何在java中正确基准测试的优秀文章,以及关于SO的大量相关问题。利用这些资源。