如何测量 Java 中经过的时间?
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/1770010/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
How do I measure time elapsed in Java?
提问by Omu
I want to have something like this:
我想要这样的东西:
public class Stream
{
public startTime;
public endTime;
public getDuration()
{
return startTime - endTime;
}
}
Also it is important that for example if the startTime it's 23:00 and endTime 1:00 to get a duration of 2:00.
同样重要的是,例如,如果 startTime 是 23:00 和 endTime 1:00 以获得 2:00 的持续时间。
Which types to use in order to accomplish this in Java?
使用哪些类型来在 Java 中完成此任务?
采纳答案by Kevin Bourrillion
Unfortunately, none of the ten answers posted so far are quite right.
不幸的是,到目前为止发布的十个答案中没有一个是完全正确的。
If you are measuring elapsed time, and you want it to be correct, you must use System.nanoTime()
. You cannot use System.currentTimeMillis()
, unless you don't mind your result being wrong.
如果您正在测量经过的时间,并且希望它是正确的,则必须使用System.nanoTime()
. 你不能使用System.currentTimeMillis()
,除非你不介意你的结果是错误的。
The purpose of nanoTime
is to measure elapsedtime, and the purpose of currentTimeMillis
is to measure wall-clocktime. You can't use the one for the other purpose. The reason is that no computer's clock is perfect; it always drifts and occasionally needs to be corrected. This correction might either happen manually, or in the case of most machines, there's a process that runs and continually issues small corrections to the system clock ("wall clock"). These tend to happen often. Another such correction happens whenever there is a leap second.
的目的nanoTime
是测量经过的时间,目的currentTimeMillis
是测量挂钟时间。您不能将其用于其他目的。原因是没有计算机的时钟是完美的;它总是漂移,偶尔需要纠正。这种更正可能是手动发生的,或者在大多数机器的情况下,有一个进程会运行并不断向系统时钟(“挂钟”)发出小的更正。这些往往经常发生。每当有闰秒时,就会发生另一个这样的修正。
Since nanoTime
's purpose is to measure elapsed time, it is unaffected by any of these small corrections. It is what you want to use. Any timings currently underway with currentTimeMillis
will be off -- possibly even negative.
由于nanoTime
的目的是测量经过的时间,因此它不受任何这些小修正的影响。这是你想要使用的。目前正在进行的任何时间安排currentTimeMillis
都将关闭——甚至可能是负面的。
You may say, "this doesn't sound like it would ever really matter that much," to which I say, maybe not, but overall, isn't correct code just better than incorrect code? Besides, nanoTime
is shorter to type anyway.
您可能会说,“这听起来并不那么重要”,对此我说,也许不是,但总的来说,正确的代码不是比错误的代码更好吗?此外,nanoTime
无论如何打字都更短。
Previously posted disclaimers about nanoTime
usually having only microsecond precision are valid. Also it can take more than a whole microsecond to invoke, depending on circumstances (as can the other one), so don't expect to time very very small intervals correctly.
之前发布的关于nanoTime
通常只有微秒精度的免责声明是有效的。此外,根据情况(与其他情况一样),调用可能需要一整微秒以上的时间,因此不要期望正确计时非常非常小的时间间隔。
回答by uckelman
If you're getting your timestamps from System.currentTimeMillis()
, then your time variables should be longs.
如果您从 获取时间戳System.currentTimeMillis()
,那么您的时间变量应该是 longs。
回答by Andreas Dolk
Java provides the static method System.currentTimeMillis()
. And that's returning a long value, so it's a good reference. A lot of other classes accept a 'timeInMillis' parameter which is long as well.
Java 提供了静态方法System.currentTimeMillis()
。这将返回一个长值,因此它是一个很好的参考。许多其他类也接受一个很长的“timeInMillis”参数。
And a lot of people find it easier to use the Joda Timelibrary to do calculations on dates and times.
很多人发现使用Joda Time库来计算日期和时间更容易。
回答by GHad
Your new class:
你的新班级:
public class TimeWatch {
long starts;
public static TimeWatch start() {
return new TimeWatch();
}
private TimeWatch() {
reset();
}
public TimeWatch reset() {
starts = System.currentTimeMillis();
return this;
}
public long time() {
long ends = System.currentTimeMillis();
return ends - starts;
}
public long time(TimeUnit unit) {
return unit.convert(time(), TimeUnit.MILLISECONDS);
}
}
Usage:
用法:
TimeWatch watch = TimeWatch.start();
// do something
long passedTimeInMs = watch.time();
long passedTimeInSeconds = watch.time(TimeUnit.SECONDS);
Afterwards, the time passed can be converted to whatever format you like, with a calender for example
之后,可以将经过的时间转换为您喜欢的任何格式,例如使用日历
Greetz, GHad
格雷茨,GHa
回答by James McMahon
If you prefer using Java's Calendar APIyou can try this,
如果你更喜欢使用 Java 的Calendar API,你可以试试这个,
Date startingTime = Calendar.getInstance().getTime();
//later on
Date now = Calendar.getInstance().getTime();
long timeElapsed = now.getTime() - startingTime.getTime();
回答by OscarRyz
Which types to use in order to accomplish this in Java?
使用哪些类型来在 Java 中完成此任务?
Answer: long
答案:长
public class Stream {
public long startTime;
public long endTime;
public long getDuration() {
return endTime - startTime;
}
// I would add
public void start() {
startTime = System.currentTimeMillis();
}
public void stop() {
endTime = System.currentTimeMillis();
}
}
Usage:
用法:
Stream s = ....
s.start();
// do something for a while
s.stop();
s.getDuration(); // gives the elapsed time in milliseconds.
That's my direct answer for your first question.
这是我对你的第一个问题的直接回答。
For the last "note" I would suggest you to use Joda Time. It contains an intervalclass suitable for what you need.
对于最后一个“注释”,我建议您使用 Joda Time。它包含一个适合您需要的间隔类。
回答by Pascal Thivent
Which types to use in order to accomplish this in Java?
使用哪些类型来在 Java 中完成此任务?
The short answer is a long
. Now, more on how to measure...
简短的回答是一个long
。现在,更多关于如何测量...
System.currentTimeMillis()
System.currentTimeMillis()
The "traditional" way to do this is indeed to use System.currentTimeMillis()
:
做到这一点的“传统”方法确实是使用System.currentTimeMillis()
:
long startTime = System.currentTimeMillis();
// ... do something ...
long estimatedTime = System.currentTimeMillis() - startTime;
o.a.c.l.t.StopWatch
oaclt 秒表
Note that Commons Lang has a StopWatchclass that can be used to measure execution time in milliseconds. It has methods methods like split()
, suspend()
, resume()
, etc that allow to take measure at different points of the execution and that you may find convenient. Have a look at it.
请注意,Commons Lang 有一个StopWatch类,可用于以毫秒为单位测量执行时间。它具有诸如split()
、suspend()
、resume()
等方法,允许在执行的不同点进行测量,并且您可能会觉得方便。看看它。
System.nanoTime()
System.nanoTime()
You may prefer to use System.nanoTime()
if you are looking for extremely precise measurements of elapsed time. From its javadoc:
System.nanoTime()
如果您正在寻找经过时间的极其精确的测量,您可能更喜欢使用。从它的javadoc:
long startTime = System.nanoTime();
// ... the code being measured ...
long estimatedTime = System.nanoTime() - startTime;
Jamon
火腿
Another option would be to use JAMon, a tool that gathers statistics(execution time, number of hit, average execution time, min, max, etc) for any code that comes between start() and stop() methods. Below, a very simple example:
另一种选择是使用JAMon,这是一种为 start() 和 stop() 方法之间的任何代码收集统计信息(执行时间、命中次数、平均执行时间、最小值、最大值等)的工具。下面,一个非常简单的例子:
import com.jamonapi.*;
...
Monitor mon=MonitorFactory.start("myFirstMonitor");
...Code Being Timed...
mon.stop();
Check out this articleon www.javaperformancetunning.com for a nice introduction.
查看www.javaperformancetunning.com 上的这篇文章以获得很好的介绍。
Using AOP
使用 AOP
Finally, if you don't want to clutter your code with these measurement (or if you can't change existing code), then AOP would be a perfect weapon. I'm not going to discuss this very deeply but I wanted at least to mention it.
最后,如果您不想用这些度量来弄乱您的代码(或者如果您不能更改现有代码),那么 AOP 将是一个完美的武器。我不会很深入地讨论这个问题,但我至少想提一下。
Below, a very simple aspect using AspectJ and JAMon (here, the short name of the pointcut will be used for the JAMon monitor, hence the call to thisJoinPoint.toShortString()
):
下面是一个使用 AspectJ 和 JAMon 的非常简单的方面(这里,切入点的短名称将用于 JAMon 监视器,因此调用thisJoinPoint.toShortString()
):
public aspect MonitorAspect {
pointcut monitor() : execution(* *.ClassToMonitor.methodToMonitor(..));
Object arround() : monitor() {
Monitor monitor = MonitorFactory.start(thisJoinPoint.toShortString());
Object returnedObject = proceed();
monitor.stop();
return returnedObject;
}
}
The pointcut definition could be easily adapted to monitor any method based on the class name, the package name, the method name, or any combination of these. Measurement is really a perfect use case for AOP.
切入点定义可以很容易地根据类名、包名、方法名或这些的任何组合来监视任何方法。测量确实是 AOP 的完美用例。
回答by David Bliss
If you are writing an application that must deal with durations of time, then please take a look at Joda-Time which has class specifically for handling Durations, Intervals, and Periods. Your getDuration()
method looks like it could return a Joda-Time Interval:
如果您正在编写一个必须处理持续时间的应用程序,那么请查看 Joda-Time,它具有专门用于处理 Duration、Intervals和 Periods 的类。您的getDuration()
方法看起来可以返回 Joda 时间间隔:
DateTime start = new DateTime(2004, 12, 25, 0, 0, 0, 0);
DateTime end = new DateTime(2005, 1, 1, 0, 0, 0, 0);
public Interval getInterval() {
Interval interval = new Interval(start, end);
}
回答by David Bliss
If the purpose is to simply print coarse timing information to your program logs, then the easy solution for Java projects is not to write your own stopwatch or timer classes, but just use the org.apache.commons.lang.time.StopWatch
class that is part of Apache Commons Lang.
如果目的只是将粗略的计时信息打印到您的程序日志,那么 Java 项目的简单解决方案不是编写您自己的秒表或计时器类,而只需使用org.apache.commons.lang.time.StopWatch
属于 Apache Commons Lang 的类。
final StopWatch stopwatch = new StopWatch();
stopwatch.start();
LOGGER.debug("Starting long calculations: {}", stopwatch);
...
LOGGER.debug("Time after key part of calcuation: {}", stopwatch);
...
LOGGER.debug("Finished calculating {}", stopwatch);
回答by Peter Lawrey
It is worth noting that
值得一提的是
- System.currentTimeMillis() has only millisecond accuracy at best. At worth its can be 16 ms on some windows systems. It has a lower cost that alternatives < 200 ns.
- System.nanoTime() is only micro-second accurate on most systems and can jump on windows systems by 100 microseconds (i.e sometimes it not as accurate as it appears)
- Calendar is a very expensive way to calculate time. (i can think of apart from XMLGregorianCalendar) Sometimes its the most appropriate solution but be aware you should only time long intervals.
- System.currentTimeMillis() 最多只有毫秒精度。在某些 Windows 系统上,它可能是 16 毫秒。它具有更低的成本,可替代 < 200 ns。
- System.nanoTime() 在大多数系统上只有微秒精度,在 windows 系统上可以跳跃 100 微秒(即有时它不像看起来那么准确)
- 日历是一种非常昂贵的时间计算方式。(除了 XMLGregorianCalendar 之外,我可以想到)有时它是最合适的解决方案,但请注意,您应该只安排很长的时间间隔。