如何在Java中计算方法的执行时间?

  1. 如何获取方法的执行时间?
  2. 是否有Timer实用程序类用于计时任务需要多长时间等?

谷歌上的大多数搜索都会返回安排线程和任务的计时器的结果,这不是我想要的。

891355 次浏览

这可能不是你想要我说的,但这是AOP的一个很好的用途。围绕你的方法鞭策一个代理拦截器,并在那里进行计时。

遗憾的是,AOP的什么、为什么和如何超出了这个答案的范围,但我可能会这样做。

编辑:这里有个链接到Spring AOP让您开始,如果您感兴趣的话。这是Live在Java中遇到的最容易访问的AOP实现。

此外,考虑到其他人非常简单的建议,我应该补充一点,AOP适用于您不希望时间之类的东西侵入您的代码的情况。但在许多情况下,这种简单易行的方法是可以的。

我选择简单的答案。对我有用。

long startTime = System.currentTimeMillis();
doReallyLongThing();
long endTime = System.currentTimeMillis();
System.out.println("That took " + (endTime - startTime) + " milliseconds");

它工作得很好。分辨率显然只有毫秒,你可以用System.nanoTime()做得更好。两者都有一些限制(操作系统调度切片等),但这工作得很好。

平均几次运行(越多越好),你会得到一个不错的主意。

如果你想要挂钟时间

long start_time = System.currentTimeMillis();object.method();long end_time = System.currentTimeMillis();long execution_time = end_time - start_time;

总有一种老式的方法:

long startTime = System.nanoTime();methodToTime();long endTime = System.nanoTime();
long duration = (endTime - startTime);  //divide by 1000000 to get milliseconds.
long startTime = System.currentTimeMillis();// code goes herelong finishTime = System.currentTimeMillis();long elapsedTime = finishTime - startTime; // elapsed time in milliseconds

我基本上做了这个的变体,但是考虑到热点编译是如何工作的,如果你想得到准确的结果,你需要抛弃前几个测量,并确保你在现实世界中使用该方法(读取特定于应用程序的)应用程序。

如果JIT决定编译它,你的数字会有很大的变化

有几种方法可以做到这一点。我通常会回到使用这样的东西:

long start = System.currentTimeMillis();// ... do something ...long end = System.currentTimeMillis();

与System.nano时间()相同;

对于更多关于基准测试方面的事情,似乎也有这样一个:http://jetm.void.fm/尽管从未尝试过。

正如“skaffman”所说,使用AOP或者您可以使用运行时字节码编织,就像单元测试方法覆盖工具用来透明地向调用的方法添加时序信息一样。

您可以查看Emma(http://downloads.sourceforge.net/emma/emma-2.0.5312-src.zip?modtime=1118607545&;big_mirror=0)等开源工具工具使用的代码。另一个开源覆盖工具是http://prdownloads.sourceforge.net/cobertura/cobertura-1.9-src.zip?download

如果你最终设法完成了你的目标,请在这里与社区分享你的蚂蚁任务/罐子。

使用分析器(JProfiler、NetBeans Profiler、Visual VM、Eclipse Profiler等)。您将获得最准确的结果并且侵入性最小。它们使用内置的JVM机制进行分析,这也可以为您提供额外的信息,如堆栈跟踪、执行路径和更全面的结果(如果需要)。

使用完全集成的分析器时,分析方法很容易。右键单击分析器->添加到根方法。然后像运行测试运行或调试器一样运行分析器。

为此,我们正在使用A的J和Java注释。如果我们需要知道一个方法的执行时间,我们简单地对它进行注释。更高级的版本可以使用自己的日志级别,可以在运行时启用和禁用。

public @interface Trace {boolean showParameters();}
@Aspectpublic class TraceAspect {[...]@Around("tracePointcut() && @annotation(trace) && !within(TraceAspect)")public Object traceAdvice ( ProceedingJintPoint jP, Trace trace ) {
Object result;// initilize timer
try {result = jp.procced();} finally {// calculate execution time}
return result;}[...]}

如果您不使用工具并希望对执行时间较短的方法进行计时,请稍作改动:执行多次,每次执行次数加倍,直到达到一秒左右。因此,调用System.nano时间的时间等等,也不System.nano时间的准确性对结果影响很大。

    int runs = 0, runsPerRound = 10;long begin = System.nanoTime(), end;do {for (int i=0; i<runsPerRound; ++i) timedMethod();end = System.nanoTime();runs += runsPerRound;runsPerRound *= 2;} while (runs < Integer.MAX_VALUE / 2 && 1000000000L > end - begin);System.out.println("Time for timedMethod() is " +0.000000001 * (end-begin) / runs + " seconds");

当然,关于使用挂钟的警告适用:JIT编译的影响,多线程/进程等因此,您需要首先执行方法很多次,以便即时编译器完成其工作,然后重复此测试多次并花费最低的执行时间。

此外,我们可以使用Apache公共资源的StopWatch类来测量时间。

示例代码

org.apache.commons.lang.time.StopWatch sw = new org.apache.commons.lang.time.StopWatch();
System.out.println("getEventFilterTreeData :: Start Time : " + sw.getTime());sw.start();
// Method execution code
sw.stop();System.out.println("getEventFilterTreeData :: End Time : " + sw.getTime());

您可以使用完美4j。非常酷的实用程序。用法简单

String watchTag = "target.SomeMethod";StopWatch stopWatch = new LoggingStopWatch(watchTag);Result result = null; // Result is a type of a return value of a methodtry {result = target.SomeMethod();stopWatch.stop(watchTag + ".success");} catch (Exception e) {stopWatch.stop(watchTag + ".fail", "Exception was " + e);throw e;}

更多的信息可以在开发者指南中找到

编辑:项目好像死了

非常好的代码。

http://www.rgagnon.com/javadetails/java-0585.html

import java.util.concurrent.TimeUnit;
long startTime = System.currentTimeMillis();........................long finishTime = System.currentTimeMillis();
String diff = millisToShortDHMS(finishTime - startTime);

/*** converts time (in milliseconds) to human-readable format*  "<dd:>hh:mm:ss"*/public static String millisToShortDHMS(long duration) {String res = "";long days  = TimeUnit.MILLISECONDS.toDays(duration);long hours = TimeUnit.MILLISECONDS.toHours(duration)- TimeUnit.DAYS.toHours(TimeUnit.MILLISECONDS.toDays(duration));long minutes = TimeUnit.MILLISECONDS.toMinutes(duration)- TimeUnit.HOURS.toMinutes(TimeUnit.MILLISECONDS.toHours(duration));long seconds = TimeUnit.MILLISECONDS.toSeconds(duration)- TimeUnit.MINUTES.toSeconds(TimeUnit.MILLISECONDS.toMinutes(duration));if (days == 0) {res = String.format("%02d:%02d:%02d", hours, minutes, seconds);}else {res = String.format("%dd%02d:%02d:%02d", days, hours, minutes, seconds);}return res;}

使用来自jCabi方面的AOP/AploJ和@Loggable注释,您可以轻松而紧凑地完成:

@Loggable(Loggable.DEBUG)public String getSomeResult() {// return some value}

对该方法的每次调用都将发送到日志级别为DEBUG的SLF4J日志记录设施。每个日志消息都将包括执行时间。

来吧,伙计们!没有人提到番石榴的方法来做到这一点(这可以说是很棒的):

import com.google.common.base.Stopwatch;
Stopwatch timer = Stopwatch.createStarted();//method invocationLOG.info("Method took: " + timer.stop());

好处是Stopwatch.toString()在选择测量的时间单位方面做得很好。也就是说,如果值很小,它将输出38 ns,如果它很长,它将显示5m3s

甚至更好:

Stopwatch timer = Stopwatch.createUnstarted();for (...) {timer.start();methodToTrackTimeFor();timer.stop();methodNotToTrackTimeFor();}LOG.info("Method took: " + timer);

注意:Google Guava需要Java1.6+

new Timer("")\{\{// code to time}}.timeMe();


public class Timer {
private final String timerName;private long started;
public Timer(String timerName) {this.timerName = timerName;this.started = System.currentTimeMillis();}
public void timeMe() {System.out.println(String.format("Execution of '%s' takes %dms.",timerName,started-System.currentTimeMillis()));}
}

System.nanoTime()是一个非常精确的系统实用程序来测量执行时间。但是要小心,如果你在先发制人的调度程序模式下运行(默认),这个实用程序实际上测量的是挂钟时间而不是CPU时间。因此,你可能会注意到从运行到运行的不同执行时间值,具体取决于系统负载。如果你寻找CPU时间,我认为在实时模式下运行你的程序就可以了。你必须使用RT linux。链接:实时编程与Linux

如果你只是想知道时间,你可以试试这个方法。

long startTime = System.currentTimeMillis();//@ Method callSystem.out.println("Total time [ms]: " + (System.currentTimeMillis() - startTime));

我修改了正确答案的代码以在几秒钟内获得结果:

long startTime = System.nanoTime();
methodCode ...
long endTime = System.nanoTime();double duration = (double)(endTime - startTime) / (Math.pow(10, 9));Log.v(TAG, "MethodName time (s) = " + duration);

System.currentTimeMillis();不是衡量算法性能的好方法。它衡量的是你作为用户观看计算机屏幕的总时间。它还包括在后台运行计算机上的其他一切所消耗的时间。如果你的工作站上运行着很多程序,这可能会产生巨大的影响。

正确的方法是使用java.lang.management包。

http://nadeausoftware.com/articles/2008/03/java_tip_how_get_cpu_and_user_time_benchmarking网站(文档链接):

  • “用户时间”是运行应用程序自己的代码所花费的时间。
  • “系统时间”是代表您的应用程序运行OS代码所花费的时间(例如I/O)。

getCpuTime()方法给你这些的总和:

import java.lang.management.ManagementFactory;import java.lang.management.ThreadMXBean;
public class CPUUtils {
/** Get CPU time in nanoseconds. */public static long getCpuTime( ) {ThreadMXBean bean = ManagementFactory.getThreadMXBean( );return bean.isCurrentThreadCpuTimeSupported( ) ?bean.getCurrentThreadCpuTime( ) : 0L;}
/** Get user time in nanoseconds. */public static long getUserTime( ) {ThreadMXBean bean = ManagementFactory.getThreadMXBean( );return bean.isCurrentThreadCpuTimeSupported( ) ?bean.getCurrentThreadUserTime( ) : 0L;}
/** Get system time in nanoseconds. */public static long getSystemTime( ) {ThreadMXBean bean = ManagementFactory.getThreadMXBean( );return bean.isCurrentThreadCpuTimeSupported( ) ?(bean.getCurrentThreadCpuTime( ) - bean.getCurrentThreadUserTime( )) : 0L;}
}

在我的机器上进行性能测量

  • System.nanoTime() : 750ns
  • System.currentTimeMillis() : 18ns

如前所述,System.nanoTime()被认为是测量经过的时间。如果在循环或类似的内部使用,请注意成本。

如果java有更好的功能支持就好了,这样需要测量的动作就可以包装成一个块:

measure {// your operation here}

在java中,这可以通过匿名函数来完成,这看起来太冗长了

public interface Timer {void wrap();}

public class Logger {
public static void logTime(Timer timer) {long start = System.currentTimeMillis();timer.wrap();System.out.println("" + (System.currentTimeMillis() - start) + "ms");}
public static void main(String a[]) {Logger.logTime(new Timer() {public void wrap() {// Your method heretimeConsumingOperation();}});
}
public static void timeConsumingOperation() {for (int i = 0; i<=10000; i++) {System.out.println("i=" +i);}}}

好的,这是一个简单的类,用于函数的简单计时。下面有一个例子。

public class Stopwatch {static long startTime;static long splitTime;static long endTime;
public Stopwatch() {start();}
public void start() {startTime = System.currentTimeMillis();splitTime = System.currentTimeMillis();endTime = System.currentTimeMillis();}
public void split() {split("");}
public void split(String tag) {endTime = System.currentTimeMillis();System.out.println("Split time for [" + tag + "]: " + (endTime - splitTime) + " ms");splitTime = endTime;}
public void end() {end("");}public void end(String tag) {endTime = System.currentTimeMillis();System.out.println("Final time for [" + tag + "]: " + (endTime - startTime) + " ms");}}

使用示例:

public static Schedule getSchedule(Activity activity_context) {String scheduleJson = null;Schedule schedule = null;/*->*/  Stopwatch stopwatch = new Stopwatch();
InputStream scheduleJsonInputStream = activity_context.getResources().openRawResource(R.raw.skating_times);/*->*/  stopwatch.split("open raw resource");
scheduleJson = FileToString.convertStreamToString(scheduleJsonInputStream);/*->*/  stopwatch.split("file to string");
schedule = new Gson().fromJson(scheduleJson, Schedule.class);/*->*/  stopwatch.split("parse Json");/*->*/  stopwatch.end("Method getSchedule");return schedule;}

控制台输出示例:

Split time for [file to string]: 672 msSplit time for [parse Json]: 893 msFinal time for [get Schedule]: 1565 ms

使用来自Java8的新API的即时持续时间

Instant start = Instant.now();Thread.sleep(5000);Instant end = Instant.now();System.out.println(Duration.between(start, end));

产出,

PT5S

在Java8中,引入了一个名为Instant的新类。根据文档:

Instant表示时间线上纳秒的开始。这类对于生成时间戳以表示机器时间很有用。瞬间的范围需要存储一个大于长。为了实现这一点,类存储一个长表示纪元秒和一个表示纳秒秒的int,它将始终在0和999,999,999之间。纪元秒被测量从1970-01-01T00:00:00Z的标准Java纪元后纪元有正值,早期的瞬间有负值。对于纪元秒和纳秒部分,a较大的值在时间线上总是比较小的值晚。

这可以用作:

Instant start = Instant.now();try {Thread.sleep(7000);} catch (InterruptedException e) {e.printStackTrace();}Instant end = Instant.now();System.out.println(Duration.between(start, end));

打印PT7.001S

Spring根据JavaDoc提供了一个实用程序类org.springframework.util.StopWatch

简单的秒表,允许对多个任务进行计时,暴露每个命名任务的总运行时间和运行时间。

用法:

StopWatch stopWatch = new StopWatch("Performance Test Result");
stopWatch.start("Method 1");doSomething1();//method to teststopWatch.stop();
stopWatch.start("Method 2");doSomething2();//method to teststopWatch.stop();
System.out.println(stopWatch.prettyPrint());

输出:

StopWatch 'Performance Test Result': running time (millis) = 12829-----------------------------------------ms     %     Task name-----------------------------------------11907  036%  Method 100922  064%  Method 2

与方面:

@Around("execution(* my.package..*.*(..))")public Object logTime(ProceedingJoinPoint joinPoint) throws Throwable {StopWatch stopWatch = new StopWatch();stopWatch.start();Object retVal = joinPoint.proceed();stopWatch.stop();log.info(" execution time: " + stopWatch.getTotalTimeMillis() + " ms");return retVal;}

您可以使用javaAgent修改java类字节,添加监视器代码dynamically.theregithub上的一些开源工具可以为您做到这一点。
如果你想自己做,只需实现javaAgent,使用javaid修改你想要监控的方法,方法之前的监控代码return.it干净的,你甚至可以监控没有源代码的系统。

使用Java8,您也可以对每个正常的方法执行类似的操作:

Object returnValue = TimeIt.printTime(() -> methodeWithReturnValue());//do stuff with your returnValue

时间就像:

public class TimeIt {
public static <T> T printTime(Callable<T> task) {T call = null;try {long startTime = System.currentTimeMillis();call = task.call();System.out.print((System.currentTimeMillis() - startTime) / 1000d + "s");} catch (Exception e) {//...}return call;}}

使用这种方法,您可以在代码中的任何地方轻松测量时间而不会破坏它。在这个简单的示例中,我只是打印时间。您可以添加一个TimeIt开关吗,例如,仅在DebugMode或其他情况下打印时间。

如果你正在使用函数,你可以这样做:

Function<Integer, Integer> yourFunction= (n) -> {return IntStream.range(0, n).reduce(0, (a, b) -> a + b);};
Integer returnValue = TimeIt.printTime2(yourFunction).apply(10000);//do stuff with your returnValue
public static <T, R> Function<T, R> printTime2(Function<T, R> task) {return (t) -> {long startTime = System.currentTimeMillis();R apply = task.apply(t);System.out.print((System.currentTimeMillis() - startTime) / 1000d+ "s");return apply;};}

把所有可能的方法聚集在一个地方。

日期

Date startDate = Calendar.getInstance().getTime();long d_StartTime = new Date().getTime();Thread.sleep(1000 * 4);Date endDate = Calendar.getInstance().getTime();long d_endTime = new Date().getTime();System.out.format("StartDate : %s, EndDate : %s \n", startDate, endDate);System.out.format("Milli = %s, ( D_Start : %s, D_End : %s ) \n", (d_endTime - d_StartTime),d_StartTime, d_endTime);

当前时间

long startTime = System.currentTimeMillis();Thread.sleep(1000 * 4);long endTime = System.currentTimeMillis();long duration = (endTime - startTime);System.out.format("Milli = %s, ( S_Start : %s, S_End : %s ) \n", duration, startTime, endTime );System.out.println("Human-Readable format : "+millisToShortDHMS( duration ) );

可读格式

public static String millisToShortDHMS(long duration) {String res = "";    // java.util.concurrent.TimeUnit;long days       = TimeUnit.MILLISECONDS.toDays(duration);long hours      = TimeUnit.MILLISECONDS.toHours(duration) -TimeUnit.DAYS.toHours(TimeUnit.MILLISECONDS.toDays(duration));long minutes    = TimeUnit.MILLISECONDS.toMinutes(duration) -TimeUnit.HOURS.toMinutes(TimeUnit.MILLISECONDS.toHours(duration));long seconds    = TimeUnit.MILLISECONDS.toSeconds(duration) -TimeUnit.MINUTES.toSeconds(TimeUnit.MILLISECONDS.toMinutes(duration));long millis     = TimeUnit.MILLISECONDS.toMillis(duration) -TimeUnit.SECONDS.toMillis(TimeUnit.MILLISECONDS.toSeconds(duration));
if (days == 0)      res = String.format("%02d:%02d:%02d.%04d", hours, minutes, seconds, millis);else                res = String.format("%dd %02d:%02d:%02d.%04d", days, hours, minutes, seconds, millis);return res;}

番石榴:谷歌秒表JAR"秒表的目标是以纳秒为单位测量经过的时间。

com.google.common.base.Stopwatch g_SW = Stopwatch.createUnstarted();g_SW.start();Thread.sleep(1000 * 4);g_SW.stop();System.out.println("Google StopWatch  : "+g_SW);

Apache Commons LangJAR"停止监视为计时提供了方便的API。

org.apache.commons.lang3.time.StopWatch sw = new StopWatch();sw.start();Thread.sleep(1000 * 4);sw.stop();System.out.println("Apache StopWatch  : "+ millisToShortDHMS(sw.getTime()) );

JODA

public static void jodaTime() throws InterruptedException, ParseException{java.text.SimpleDateFormat ms_SDF = new SimpleDateFormat("yyyy/MM/dd HH:mm:ss.SSS");String start = ms_SDF.format( new Date() ); // java.util.Date
Thread.sleep(10000);
String end = ms_SDF.format( new Date() );System.out.println("Start:"+start+"\t Stop:"+end);
Date date_1 = ms_SDF.parse(start);Date date_2 = ms_SDF.parse(end);Interval interval = new org.joda.time.Interval( date_1.getTime(), date_2.getTime() );Period period = interval.toPeriod(); //org.joda.time.Period
System.out.format("%dY/%dM/%dD, %02d:%02d:%02d.%04d \n",period.getYears(), period.getMonths(), period.getDays(),period.getHours(), period.getMinutes(), period.getSeconds(), period.getMillis());}

Java日期时间API从Java8"一个持续时间对象表示两个即时对象之间的一段时间。

Instant start = java.time.Instant.now();Thread.sleep(1000);Instant end = java.time.Instant.now();Duration between = java.time.Duration.between(start, end);System.out.println( between ); // PT1.001SSystem.out.format("%dD, %02d:%02d:%02d.%04d \n", between.toDays(),between.toHours(), between.toMinutes(), between.getSeconds(), between.toMillis()); // 0D, 00:00:01.1001

Spring框架提供停止监视实用程序类来测量Java中的运行时间。

StopWatch sw = new org.springframework.util.StopWatch();sw.start("Method-1"); // Start a named taskThread.sleep(500);sw.stop();
sw.start("Method-2");Thread.sleep(300);sw.stop();
sw.start("Method-3");Thread.sleep(200);sw.stop();
System.out.println("Total time in milliseconds for all tasks :\n"+sw.getTotalTimeMillis());System.out.println("Table describing all tasks performed :\n"+sw.prettyPrint());
System.out.format("Time taken by the last task : [%s]:[%d]",sw.getLastTaskName(),sw.getLastTaskTimeMillis());
System.out.println("\n Array of the data for tasks performed « Task Name: Time Taken");TaskInfo[] listofTasks = sw.getTaskInfo();for (TaskInfo task : listofTasks) {System.out.format("[%s]:[%d]\n",task.getTaskName(), task.getTimeMillis());}

输出:

Total time in milliseconds for all tasks :999Table describing all tasks performed :StopWatch '': running time (millis) = 999-----------------------------------------ms     %     Task name-----------------------------------------00500  050%  Method-100299  030%  Method-200200  020%  Method-3
Time taken by the last task : [Method-3]:[200]Array of the data for tasks performed « Task Name: Time Taken[Method-1]:[500][Method-2]:[299][Method-3]:[200]

JEP 230:微基准套件

仅供参考,JEP 230:微基准套件是一个OpenJDK项目:

在JDK源代码中添加一套基本的微基准测试,使开发人员可以轻松运行现有的微基准测试并创建新的微基准测试。

这个功能出现在Java12

Java微基准线束(JMH)

有关Java的早期版本,请查看JEP 230所基于的Java微基准线束(JMH)项目。

这是一个漂亮的打印字符串准备格式化的秒经过类似于谷歌搜索时间搜索:

        long startTime = System.nanoTime();//  ... methodToTime();long endTime = System.nanoTime();long duration = (endTime - startTime);long seconds = (duration / 1000) % 60;// formatedSeconds = (0.xy seconds)String formatedSeconds = String.format("(0.%d seconds)", seconds);System.out.println("formatedSeconds = "+ formatedSeconds);// i.e actual formatedSeconds = (0.52 seconds)

我实现了一个简单的计时器,我认为它非常有用:

public class Timer{private static long start_time;
public static double tic(){return start_time = System.nanoTime();}
public static double toc(){return (System.nanoTime()-start_time)/1000000000.0;}
}

这样你就可以对一个或多个动作进行计时:

Timer.tic();// Code 1System.out.println("Code 1 runtime: "+Timer.toc()+" seconds.");// Code 2System.out.println("(Code 1 + Code 2) runtime: "+Timer.toc()+"seconds");Timer.tic();// Code 3System.out.println("Code 3 runtime: "+Timer.toc()+" seconds.");

在java ee中对我有效的策略是:

  1. 创建一个带有@AroundInvoke注释的方法的类;

    @Singletonpublic class TimedInterceptor implements Serializable {
    @AroundInvokepublic Object logMethod(InvocationContext ic) throws Exception {Date start = new Date();Object result = ic.proceed();Date end = new Date();System.out.println("time: " + (end.getTime - start.getTime()));return result;}}
  2. Annotate the method that you want to monitoring:

    @Interceptors(TimedInterceptor.class)public void onMessage(final Message message) { ...

I hope this can help.

您可以使用指标库,该库提供各种测量仪器。添加依赖项:

<dependencies><dependency><groupId>io.dropwizard.metrics</groupId><artifactId>metrics-core</artifactId><version>${metrics.version}</version></dependency></dependencies>

并为您的环境配置它。

方法可以用@陈志立注释:

@Timedpublic void exampleMethod(){// some code}

或者用定时器包装的一段代码:

final Timer timer = metricsRegistry.timer("some_name");final Timer.Context context = timer.time();// timed codecontext.stop();

聚合的指标可以导出到控制台、JMX、CSV或其他。

@Timed指标输出示例:

com.example.ExampleService.exampleMethodcount = 2mean rate = 3.11 calls/minute1-minute rate = 0.96 calls/minute5-minute rate = 0.20 calls/minute15-minute rate = 0.07 calls/minutemin = 17.01 millisecondsmax = 1006.68 millisecondsmean = 511.84 millisecondsstddev = 699.80 millisecondsmedian = 511.84 milliseconds75% <= 1006.68 milliseconds95% <= 1006.68 milliseconds98% <= 1006.68 milliseconds99% <= 1006.68 milliseconds99.9% <= 1006.68 milliseconds

您可以使用来自Spring Core项目的秒表类:

代码:

StopWatch stopWatch = new StopWatch()stopWatch.start();  //start stopwatch// write your function or line of code.stopWatch.stop();  //stop stopwatchstopWatch.getTotalTimeMillis() ; ///get total time

秒表文档:简单的秒表,允许对多个任务进行计时,暴露每个命名任务的总运行时间和运行时间。隐藏使用System.currentTimeMillis(),提高应用程序代码的易读性并降低计算错误的可能性。请注意,此对象不是设计为线程安全的,也不使用同步。此类通常用于验证概念验证期间和开发中的性能,而不是作为生产应用程序的一部分。

我已经编写了一个方法,以可读的形式打印方法执行时间。例如,要计算100万的阶乘,大约需要9分钟。所以执行时间打印为:

Execution Time: 9 Minutes, 36 Seconds, 237 MicroSeconds, 806193 NanoSeconds

代码在这里:

public class series{public static void main(String[] args){long startTime = System.nanoTime();
long n = 10_00_000;printFactorial(n);
long endTime = System.nanoTime();printExecutionTime(startTime, endTime);
}
public static void printExecutionTime(long startTime, long endTime){long time_ns = endTime - startTime;long time_ms = TimeUnit.NANOSECONDS.toMillis(time_ns);long time_sec = TimeUnit.NANOSECONDS.toSeconds(time_ns);long time_min = TimeUnit.NANOSECONDS.toMinutes(time_ns);long time_hour = TimeUnit.NANOSECONDS.toHours(time_ns);
System.out.print("\nExecution Time: ");if(time_hour > 0)System.out.print(time_hour + " Hours, ");if(time_min > 0)System.out.print(time_min % 60 + " Minutes, ");if(time_sec > 0)System.out.print(time_sec % 60 + " Seconds, ");if(time_ms > 0)System.out.print(time_ms % 1E+3 + " MicroSeconds, ");if(time_ns > 0)System.out.print(time_ns % 1E+6 + " NanoSeconds");}}

对于Java 8+,另一种可能的解决方案(更通用,func风格且没有方面)可能是创建一些实用方法,接受代码作为参数

public static <T> T timed (String description, Consumer<String> out, Supplier<T> code) {final LocalDateTime start = LocalDateTime.now ();T res = code.get ();final long execTime = Duration.between (start, LocalDateTime.now ()).toMillis ();out.accept (String.format ("%s: %d ms", description, execTime));return res;}

调用代码可以是这样的:

public static void main (String[] args) throws InterruptedException {timed ("Simple example", System.out::println, Timing::myCode);}
public static Object myCode () {try {Thread.sleep (1500);} catch (InterruptedException e) {e.printStackTrace ();}return null;}

纯JavaSE代码,无需添加依赖,使用TimeTracedExecuter

public static void main(String[] args) {
Integer square = new TimeTracedExecutor<>(Main::calculateSquare).executeWithInput("calculate square of num",5,logger);
}public static int calculateSquare(int num){return num*num;}

会产生这样的结果:

INFO: It took 3 milliseconds to calculate square of num

自定义可重用类:执行人

import java.text.NumberFormat;import java.time.Duration;import java.time.Instant;import java.util.function.Function;import java.util.logging.Logger;
public class TimeTracedExecutor<T,R> {Function<T,R> methodToExecute;
public TimeTracedExecutor(Function<T, R> methodToExecute) {this.methodToExecute = methodToExecute;}
public R executeWithInput(String taskDescription, T t, Logger logger){Instant start = Instant.now();R r= methodToExecute.apply(t);Instant finish = Instant.now();String format = "It took %s milliseconds to "+taskDescription;String elapsedTime = NumberFormat.getNumberInstance().format(Duration.between(start, finish).toMillis());logger.info(String.format(format, elapsedTime));return r;}}

在Spring框架中,我们有一个名为StopWatch(org.springframework.util.StopWatch)的调用

//measuring elapsed time using Spring StopWatchStopWatch watch = new StopWatch();watch.start();for(int i=0; i< 1000; i++){Object obj = new Object();}watch.stop();System.out.println("Total execution time to create 1000 objects in Java using StopWatch in millis: "+ watch.getTotalTimeMillis());

也可以实现Timer接口并在类的任何方法上执行

import java.util.function.*;
public interface Timer {
default void timeIt(Runnable r) {timeIt(() -> { r.run(); return 0;});}
default <S,T> T timeIt(Function<S,T> fun, S arg) {long start = System.nanoTime();T result = fun.apply(arg);long stop = System.nanoTime();System.out.println("Time: " + (stop-start)/1000000.0 + " msec");return result;}
default <T> T timeIt(Supplier<T> s) {return timeIt(obj -> s.get(), null);}}

用法:

class MyClass implements Timer ..
timeIt(this::myFunction);

这里有很多有效的答案,所有这些都在方法中实现。为了制作用于计时的通用方法,我通常有一个由以下内容组成的Timing类。

public record TimedResult<T>(T result, Duration duration) {}
public static Duration time(Runnable r) {var s = Instant.now();r.run();var dur = Duration.between(s, Instant.now());return dur;}
public static <T> TimedResult<T> time(Callable<T> r) throws Exception {var s = Instant.now();T res = r.call();var dur = Duration.between(s, Instant.now());return new TimedResult<>(res, dur);}

这足以通过不可用可调用

Duration result = Timing.time(() -> {// do some work.});
TimedResult<String> result = Timing.time(() -> {// do some work.return "answer";});
Duration timeTaken = result.duration();String answer = result.result();