如何测量线程从新到结束的确切时间 java
How to measure how long a thread will exactly take from new to end in java
题目:
- 有没有办法获得线程从新建到结束所需的确切时间?
- 为什么每次的结果都相差很大(见下面代码)?
代码:
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);
}
通常与衡量执行时间更相关,即执行run()
方法所花费的时间。这个时间在不同的运行之间通常是相似的。
创建一个新的 Thread
对象是相当昂贵的,并且取决于系统当前可用的资源,这就是为什么 [=11] 之间的时间差异很大=] 创建及其执行。更重要的是,在销毁线程之前,有一个清理过程也会占用大量时间。
优化线程管理时间 (creations/destruction) 的一种方法是使用 ThreadPool
或 ExecutorService
。有关详细信息,请参阅 Oracle concurrency tutorial。
你编造了一个非常糟糕的测量示例。
首先,使用 new 创建一个新线程非常便宜(它是一个普通的 java 对象)。但是您实际上包括 class 匿名 Runnable 的加载时间。这将涉及 I/O,因此 可以预期 执行时间变化很大,尤其是第一个 运行。
那么您正在以毫秒为单位测量时间。但是系统时间不一定具有实际的毫秒精度(请阅读 System.currentTimeMillis 的 java 文档)。此外,您尝试测量的内容大多数情况下会在 少于 的时间内执行 。
您的 Runnable 没有明显的副作用,因此 JIT 可能会在短暂的预热后优化整个代码。几 运行s 之后,运行nable 实际上可能根本不需要任何时间。
您正在轮询以确定其他线程何时结束。那就是让 CPU(好吧,如果你有多个核心,就一个核心)忙于无所事事。对于单核机器,这意味着平均有 50% 的时间用于检查线程是否处于活动状态。根据 OS 调度器 运行 线程的方式,这是另一个变化来源。
总而言之,您已经制作了一个 微基准测试 ,并且您已经踩到了微基准测试在 java 中可能遇到的所有最常见的陷阱。 java 中的基准测试需要小心,否则您将测量任何东西,但不会测量您实际上想要测量的代码的性能。在 java 中有基准测试框架和关于如何正确进行基准测试的优秀文章,以及 SO 上的大量相关问题。利用这些资源。
题目:
- 有没有办法获得线程从新建到结束所需的确切时间?
- 为什么每次的结果都相差很大(见下面代码)?
代码:
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);
}
通常与衡量执行时间更相关,即执行
run()
方法所花费的时间。这个时间在不同的运行之间通常是相似的。创建一个新的
Thread
对象是相当昂贵的,并且取决于系统当前可用的资源,这就是为什么 [=11] 之间的时间差异很大=] 创建及其执行。更重要的是,在销毁线程之前,有一个清理过程也会占用大量时间。
优化线程管理时间 (creations/destruction) 的一种方法是使用 ThreadPool
或 ExecutorService
。有关详细信息,请参阅 Oracle concurrency tutorial。
你编造了一个非常糟糕的测量示例。
首先,使用 new 创建一个新线程非常便宜(它是一个普通的 java 对象)。但是您实际上包括 class 匿名 Runnable 的加载时间。这将涉及 I/O,因此 可以预期 执行时间变化很大,尤其是第一个 运行。
那么您正在以毫秒为单位测量时间。但是系统时间不一定具有实际的毫秒精度(请阅读 System.currentTimeMillis 的 java 文档)。此外,您尝试测量的内容大多数情况下会在 少于 的时间内执行 。
您的 Runnable 没有明显的副作用,因此 JIT 可能会在短暂的预热后优化整个代码。几 运行s 之后,运行nable 实际上可能根本不需要任何时间。
您正在轮询以确定其他线程何时结束。那就是让 CPU(好吧,如果你有多个核心,就一个核心)忙于无所事事。对于单核机器,这意味着平均有 50% 的时间用于检查线程是否处于活动状态。根据 OS 调度器 运行 线程的方式,这是另一个变化来源。
总而言之,您已经制作了一个 微基准测试 ,并且您已经踩到了微基准测试在 java 中可能遇到的所有最常见的陷阱。 java 中的基准测试需要小心,否则您将测量任何东西,但不会测量您实际上想要测量的代码的性能。在 java 中有基准测试框架和关于如何正确进行基准测试的优秀文章,以及 SO 上的大量相关问题。利用这些资源。