搬砖的我们 特别是Java开发的童鞋们, 经常需要通过记录开始时间和结束时间,然后通过计算差值,得到时间差,如下面的代码:
long start = System.currentTimeMillis();
long end = System.currentTimeMillis();
System.out.println("执行耗时:" + (end - start));
其实spring 这个包org.springframework.util.StopWatch的工具类也可以实现计算时间差,如下代码:
StopWatch stopWatch = new StopWatch();
// 或者指定任务名
StopWatch stopWatch = new StopWatch("name");
// 开始计时
stopWatch.start();
// 结束计时
stopWatch.stop();
// 计算时差
stopWatch.getTotalTimeSeconds();
// 计算时差
stopWatch.shortSummary();
优点:
1、Spring自带工具类,使用方便简单。
2、性能消耗相对较小,并且最大程度的保证了start与stop之间的时间记录的准确性。
3、可以指定任务名,更直观的显示记录结果。
缺点:
1、一个StopWatch实例一次只能开启一个task,不能同时start多个task,并且在该task未stop之前不能start一个新的task,必须在该task stop之后才能开启新的task,若要一次开启多个,需要new不同的StopWatch实例。
.............................................来看看Spring中stopWatch的源代码....................................................
public ConfigurableApplicationContext run(String... args) {
(1) StopWatch stopWatch = new StopWatch();
(2)stopWatch.start();
ConfigurableApplicationContext context = null;
Collection<SpringBootExceptionReporter> exceptionReporters = new ArrayList();
this.configureHeadlessProperty();
SpringApplicationRunListeners listeners = this.getRunListeners(args);
listeners.starting();
Collection exceptionReporters;
try {
ApplicationArguments applicationArguments = new DefaultApplicationArguments(args);
ConfigurableEnvironment environment = this.prepareEnvironment(listeners, applicationArguments);
this.configureIgnoreBeanInfo(environment);
Banner printedBanner = this.printBanner(environment);
context = this.createApplicationContext();
exceptionReporters = this.getSpringFactoriesInstances(SpringBootExceptionReporter.class, new Class[]{ConfigurableApplicationContext.class}, context);
this.prepareContext(context, environment, listeners, applicationArguments, printedBanner);
this.refreshContext(context);
this.afterRefresh(context, applicationArguments);
(3) stopWatch.stop();
if (this.logStartupInfo) {
(4) (new StartupInfoLogger(this.mainApplicationClass)).logStarted(this.getApplicationLog(), stopWatch);
}
listeners.started(context);
this.callRunners(context, applicationArguments);
} catch (Throwable var10) {
this.handleRunFailure(context, var10, exceptionReporters, listeners);
throw new IllegalStateException(var10);
}
try {
listeners.running(context);
return context;
} catch (Throwable var9) {
this.handleRunFailure(context, var9, exceptionReporters, (SpringApplicationRunListeners)null);
throw new IllegalStateException(var9);
}
}
我们重点来关注上面的源代码中标注的(1),(2),(3),(4)的部分,这就是启动时监控加载个配置类的计时器,我们继续来看下(4)对应的方法:logStarted(this.getApplicationLog(), stopWatch);stopWatch作为参数传递该该方法,看看该方法具体实现:
================ logStarted()==================================================
public void logStarted(Log log, StopWatch stopWatch) {
if (log.isInfoEnabled()) {
log.info(this.getStartedMessage(stopWatch));
}
}
==============================getStartedMessage()=====================================
private StringBuilder getStartedMessage(StopWatch stopWatch) {
StringBuilder message = new StringBuilder();
message.append("Started ");
message.append(this.getApplicationName());
message.append(" in ");
message.append(stopWatch.getTotalTimeSeconds());
try {
double uptime = (double)ManagementFactory.getRuntimeMXBean().getUptime() / 1000.0D;
message.append(" seconds (JVM running for " + uptime + ")");
} catch (Throwable var5) {
}
return message;
}
Stopwatch 对程序部分代码进行计时(ms级别),适用于同步单线程代码块。StopWatch实例一次只能开启一个task,不能同时start多个task,并且在该task未stop之前不能start一个新的task,必须在该task stop之后才能开启新的task,若要一次开启多个,需要new不同的StopWatch实例
========================================================================
// 只输出运行多少秒
Stopwatch stopwatch = Stopwatch.createStarted();
stopwatch.stop();
System.out.println(stopwatch.elapsed(TimeUnit.SECONDS) + "s");
//
StopWatch sw = new StopWatch("test");
sw.start("task1");
// do something
Thread.sleep(100);
sw.stop();
sw.start("task2");
// do something
Thread.sleep(200);
sw.stop();
System.out.println(sw.prettyPrint());
运行结果==================================================================
2s
StopWatch 'test': running time (millis) = 308
-----------------------------------------
ms % Task name
-----------------------------------------
00104 034% task1
00204 066% task2
============================================================================