TimeUnit源码解析

TimeUnit是一个枚举类型,共有NANOSECONDS,MICROSECONDS,MILLISECONDS,SECONDS,MINUTES,HOURS,DAYS 7个粒度,分别代表纳秒,微妙,毫秒,秒,分。小时。天。

所以也定义了7个转换方法。这里没有定义为抽象方法,是为了输出doc,因为定义为抽象方法就无法抽出doc了。抛出AbstractMethodError是为了让子类型全都重写这7个方法,否则使用未实现的抽象方法会抛AbstractMethodError。

public long toNanos(long duration) {
        throw new AbstractMethodError();
    }

  
    public long toMicros(long duration) {
        throw new AbstractMethodError();
    }

   
    public long toMillis(long duration) {
        throw new AbstractMethodError();
    }

   
    public long toSeconds(long duration) {
        throw new AbstractMethodError();
    }

  
    public long toMinutes(long duration) {
        throw new AbstractMethodError();
    }

   
    public long toHours(long duration) {
        throw new AbstractMethodError();
    }

    public long toDays(long duration) {
        throw new AbstractMethodError();
    }

除了7个转换方法,还有一个convert方法,实现的时候也是调用了上面的7个转换的方法之一。

public long convert(long sourceDuration, java.util.concurrent.TimeUnit sourceUnit) {
    throw new AbstractMethodError();
}

分析之前先将各个粒度的数值列出来,C0是一个单位的纳秒,C1是一个单位的微秒,是C0的1000倍......依次类推

static final long C0 = 1L;
static final long C1 = C0 * 1000L;
static final long C2 = C1 * 1000L;
static final long C3 = C2 * 1000L;
static final long C4 = C3 * 60L;
static final long C5 = C4 * 60L;
static final long C6 = C5 * 24L;

static final long MAX = Long.MAX_VALUE;

现在单独抽出一个HOURS来看看。

HOURS {
    public long toNanos(long d)   { return x(d, C5/C0, MAX/(C5/C0)); }
    public long toMicros(long d)  { return x(d, C5/C1, MAX/(C5/C1)); }
    public long toMillis(long d)  { return x(d, C5/C2, MAX/(C5/C2)); }
    public long toSeconds(long d) { return x(d, C5/C3, MAX/(C5/C3)); }
    public long toMinutes(long d) { return x(d, C5/C4, MAX/(C5/C4)); }
    public long toHours(long d)   { return d; }
    public long toDays(long d)    { return d/(C6/C5); }
    public long convert(long d, java.util.concurrent.TimeUnit u) { return u.toHours(d); }
    int excessNanos(long d, long m) { return 0; }
}

可以看到,convert也是调用了toHours方法。toDays没有疑问,将输入的小时除以粒度的比值,得到粒度更大的天数,其实就是除以24。那么toNanos调用的x方法是干什么用的呢?我们看看它的定义:

/**
 * Scale d by m, checking for overflow.
 * This has a short name to make above code more readable.
 */
static long x(long d, long m, long over) {
    if (d >  over) return Long.MAX_VALUE;
    if (d < -over) return Long.MIN_VALUE;
    return d * m;
}

套用HOURS,d就是输入的小时数,m是纳秒转换为小时的比值,即为C5/C0,over是转化为纳米所能允许的最大小时数,x方法为了防止overflow,进行了判断:

 if (d >  over) return Long.MAX_VALUE; 

if (d < -over) return Long.MIN_VALUE;

d就是要换算的数值,m是换算比例,乘积是换算的结果,这时候跟小学时期换算单位是一样的。因为粒度大于等于毫秒的,总可以整个换算成毫秒,并没有遗留纳秒部分,所以全部返回0。

还有一个excessNanos方法是干什么用的呢?在HOURS里只是返回一个0。excessNanos注释可以看到,这是输入一个数值d和它的微秒部分m,然后抽出纳秒部分。

/**
 * Utility to compute the excess-nanosecond argument to wait,
 * sleep, join.
 * @param d the duration
 * @param m the number of milliseconds
 * @return the number of nanoseconds
 */
abstract int excessNanos(long d, long m);

拿MICROSECONDS来说,计算的过程是总值d乘以换算比例得到总纳秒值,然后减去微秒部分m换算成的纳秒值,就得到了纳秒部分。

int excessNanos(long d, long m) { return (int)((d*C1) - (m*C2)); }

TimeUnit封装了Thread的join,sleep方法与Object的wait方法,有利于简化代码,提高可读性。excessNanos方法在这里提取了纳秒部分,派上了用场。

public void sleep(long timeout) throws InterruptedException {
    if (timeout > 0) {
        long ms = toMillis(timeout);
        int ns = excessNanos(timeout, ms);
        Thread.sleep(ms, ns);
    }
}

转载于:https://my.oschina.net/u/3686484/blog/1548579

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值