耗时打印
来源于 Hikari
源码
1. 源码
import java.util.concurrent.TimeUnit;
import static java.util.concurrent.TimeUnit.*;
import static java.util.concurrent.TimeUnit.NANOSECONDS;
public interface ClockSource {
/**
* 时钟源,也是 ClockSource 接口的具体实现
*/
static ClockSource CLOCK = Factory.create();
/**
* Get the current time-stamp (resolution is opaque).
* 返回当前时间戳,而而这个时间戳的单位是不透明的,根据现有实现,可能为毫秒,也可能为纳秒
*
* @return 当前时间戳
*/
static long currentTime() {
return CLOCK.currentTime0();
}
long currentTime0();
/**
* 将入参时间戳转换为毫秒,入参时间戳最好是 ClockSource#currentTime() 返回的单位
*
* @param time 当前实例返回的时间戳
* @return 毫秒计的时间戳
*/
static long toMillis(long time) {
return CLOCK.toMillis0(time);
}
long toMillis0(long time);
/**
* 将入参时间戳转换为纳秒,入参时间戳最好是 ClockSource#currentTime() 返回的单位
*
* @param time 当前实例返回的时间戳
* @return 纳秒计的时间戳
*/
static long toNanos(long time) {
return CLOCK.toNanos0(time);
}
long toNanos0(long time);
/**
* 返回当前时间与入参时间的间隔,返回间隔时间以毫秒为单位,入参应是当前实例返回的时间戳
*
* @param startTime 当前实例返回的时间戳
* @return 返回当前时间与入参时间的间隔,返回间隔时间以毫秒为单位
*/
static long elapsedMillis(long startTime) {
return CLOCK.elapsedMillis0(startTime);
}
long elapsedMillis0(long startTime);
/**
* Get the difference in milliseconds between two opaque time-stamps returned
* by currentTime().
*
* @param startTime an opaque time-stamp returned by an instance of this class
* @param endTime an opaque time-stamp returned by an instance of this class
* @return the elapsed time between startTime and endTime in milliseconds
*/
static long elapsedMillis(long startTime, long endTime) {
return CLOCK.elapsedMillis0(startTime, endTime);
}
long elapsedMillis0(long startTime, long endTime);
/**
* Convert an opaque time-stamp returned by currentTime() into an
* elapsed time in milliseconds, based on the current instant in time.
*
* @param startTime an opaque time-stamp returned by an instance of this class
* @return the elapsed time between startTime and now in milliseconds
*/
static long elapsedNanos(long startTime) {
return CLOCK.elapsedNanos0(startTime);
}
long elapsedNanos0(long startTime);
/**
* Get the difference in nanoseconds between two opaque time-stamps returned
* by currentTime().
*
* @param startTime an opaque time-stamp returned by an instance of this class
* @param endTime an opaque time-stamp returned by an instance of this class
* @return the elapsed time between startTime and endTime in nanoseconds
*/
static long elapsedNanos(long startTime, long endTime) {
return CLOCK.elapsedNanos0(startTime, endTime);
}
long elapsedNanos0(long startTime, long endTime);
/**
* Return the specified opaque time-stamp plus the specified number of milliseconds.
*
* @param time an opaque time-stamp
* @param millis milliseconds to add
* @return a new opaque time-stamp
*/
static long plusMillis(long time, long millis) {
return CLOCK.plusMillis0(time, millis);
}
long plusMillis0(long time, long millis);
/**
* 当前实例返回的时间戳的单位
*
* @return TimeUnit instance
*/
static TimeUnit getSourceTimeUnit() {
return CLOCK.getSourceTimeUnit0();
}
TimeUnit getSourceTimeUnit0();
/**
* Get a String representation of the elapsed time in appropriate magnitude terminology.
*
* @param startTime an opaque time-stamp
* @param endTime an opaque time-stamp
* @return a string representation of the elapsed time interval
*/
static String elapsedDisplayString(long startTime, long endTime) {
return CLOCK.elapsedDisplayString0(startTime, endTime);
}
default String elapsedDisplayString0(long startTime, long endTime) {
long elapsedNanos = elapsedNanos0(startTime, endTime);
StringBuilder sb = new StringBuilder(elapsedNanos < 0 ? "-" : "");
elapsedNanos = Math.abs(elapsedNanos);
for (TimeUnit unit : TIMEUNITS_DESCENDING) {
long converted = unit.convert(elapsedNanos, NANOSECONDS);
if (converted > 0) {
sb.append(converted).append(TIMEUNIT_DISPLAY_VALUES[unit.ordinal()]);
elapsedNanos -= NANOSECONDS.convert(converted, unit);
}
}
return sb.toString();
}
TimeUnit[] TIMEUNITS_DESCENDING = {DAYS, HOURS, MINUTES, SECONDS, MILLISECONDS, MICROSECONDS, NANOSECONDS};
String[] TIMEUNIT_DISPLAY_VALUES = {"ns", "µs", "ms", "s", "m", "h", "d"};
/**
* Factory class used to create a platform-specific ClockSource.
*/
class Factory {
private static ClockSource create() {
String os = System.getProperty("os.name");
if ("Mac OS X".equals(os)) {
return new MillisecondClockSource();
}
return new NanosecondClockSource();
}
}
final class MillisecondClockSource implements ClockSource {
/**
* {@inheritDoc}
*/
@Override
public long currentTime0() {
return System.currentTimeMillis();
}
/**
* {@inheritDoc}
*/
@Override
public long elapsedMillis0(final long startTime) {
return System.currentTimeMillis() - startTime;
}
/**
* {@inheritDoc}
*/
@Override
public long elapsedMillis0(final long startTime, final long endTime) {
return endTime - startTime;
}
/**
* {@inheritDoc}
*/
@Override
public long elapsedNanos0(final long startTime) {
return MILLISECONDS.toNanos(System.currentTimeMillis() - startTime);
}
/**
* {@inheritDoc}
*/
@Override
public long elapsedNanos0(final long startTime, final long endTime) {
return MILLISECONDS.toNanos(endTime - startTime);
}
/**
* {@inheritDoc}
*/
@Override
public long toMillis0(final long time) {
return time;
}
/**
* {@inheritDoc}
*/
@Override
public long toNanos0(final long time) {
return MILLISECONDS.toNanos(time);
}
/**
* {@inheritDoc}
*/
@Override
public long plusMillis0(final long time, final long millis) {
return time + millis;
}
/**
* {@inheritDoc}
*/
@Override
public TimeUnit getSourceTimeUnit0() {
return MILLISECONDS;
}
}
class NanosecondClockSource implements ClockSource {
/**
* {@inheritDoc}
*/
@Override
public long currentTime0() {
return System.nanoTime();
}
/**
* {@inheritDoc}
*/
@Override
public long toMillis0(final long time) {
return NANOSECONDS.toMillis(time);
}
/**
* {@inheritDoc}
*/
@Override
public long toNanos0(final long time) {
return time;
}
/**
* {@inheritDoc}
*/
@Override
public long elapsedMillis0(final long startTime) {
return NANOSECONDS.toMillis(System.nanoTime() - startTime);
}
/**
* {@inheritDoc}
*/
@Override
public long elapsedMillis0(final long startTime, final long endTime) {
return NANOSECONDS.toMillis(endTime - startTime);
}
/**
* {@inheritDoc}
*/
@Override
public long elapsedNanos0(final long startTime) {
return System.nanoTime() - startTime;
}
/**
* {@inheritDoc}
*/
@Override
public long elapsedNanos0(final long startTime, final long endTime) {
return endTime - startTime;
}
/**
* {@inheritDoc}
*/
@Override
public long plusMillis0(final long time, final long millis) {
return time + MILLISECONDS.toNanos(millis);
}
/**
* {@inheritDoc}
*/
@Override
public TimeUnit getSourceTimeUnit0() {
return NANOSECONDS;
}
}
}
2. 输出格式化时间间隔的关键代码
default String elapsedDisplayString0(long startTime, long endTime) {
long elapsedNanos = elapsedNanos0(startTime, endTime);
StringBuilder sb = new StringBuilder(elapsedNanos < 0 ? "-" : "");
elapsedNanos = Math.abs(elapsedNanos);
for (TimeUnit unit : TIMEUNITS_DESCENDING) {
long converted = unit.convert(elapsedNanos, NANOSECONDS);
if (converted > 0) {
sb.append(converted).append(TIMEUNIT_DISPLAY_VALUES[unit.ordinal()]);
elapsedNanos -= NANOSECONDS.convert(converted, unit);
}
}
return sb.toString();
}
TimeUnit[] TIMEUNITS_DESCENDING = {DAYS, HOURS, MINUTES, SECONDS, MILLISECONDS, MICROSECONDS, NANOSECONDS};
String[] TIMEUNIT_DISPLAY_VALUES = {"ns", "µs", "ms", "s", "m", "h", "d"};
思考
1. 设计模式
工厂模式
ClockSource.Factory 体现的是什么工厂设计模式呢?简单工厂设计模式?虽然没有根据入参创建对象,但是根据了当前系统配置创建对象。
2. 与 StopWatch 之类的组合
ClockSource 之类的这种工具类一般用于计时,而它格式化字符串的入参一般只接受获取的实例返回时间戳(虽然可以通过方法获取其时间戳的单位,但是总是不方便使用),而 StopWatch 之类的工具类提供了计时的更方便也封装更好的方法。
如果只需要它的时间间隔格式化,可以直接提取出来到一个 format 工具类中?