问题:
代码:
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);
}
答案 0 :(得分:1)
衡量执行时间通常更为相关,即执行run()
方法所需的时间。不同运行之间的时间通常相似。
新Thread
对象的创建成本相当高,并且取决于系统当前可用的资源,这就是为什么在创建Thread
之间可能存在很大差异的原因。它的执行。更重要的是,在破坏线程之前,还有一个清理过程也会占用大量时间。
优化线程管理时间(创建/销毁)的一种方法是使用ThreadPool
或ExecutorService
。有关详细信息,请参阅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的大量相关问题。利用这些资源。