耗时打印

来源于 Hikari

image

源码

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 工具类中?

posted @ 2023-03-11 17:25  YangDanMua  阅读(58)  评论(0编辑  收藏  举报