TimeUnit类源码详解(concurrent包下的时间工具类)

目录

 

1、TimeUnit介绍与基本使用

2、其它的操作方法

2.1、timedWait方法

2.2、timedJoin方法

2.3、sleep方法

2.4、int excessNanos(long d, long m) 方法


1、TimeUnit介绍与基本使用

TimeUnit类的作用:用于时间的换算,比如纳秒,微秒,毫秒,秒,分钟,小时,天等等的换算。

下面看看TimeUnit的源码,提供了每个时间单位的换算方法。

public enum TimeUnit {
    // 纳秒转换工具
    NANOSECONDS {
        public long toNanos(long d)   { return d; }
        public long toMicros(long d)  { return d/(C1/C0); }
        public long toMillis(long d)  { return d/(C2/C0); }
        public long toSeconds(long d) { return d/(C3/C0); }
        public long toMinutes(long d) { return d/(C4/C0); }
        public long toHours(long d)   { return d/(C5/C0); }
        public long toDays(long d)    { return d/(C6/C0); }
        public long convert(long d, TimeUnit u) { return u.toNanos(d); }
        int excessNanos(long d, long m) { return (int)(d - (m*C2)); }
    },

    // 微秒转换工具
    MICROSECONDS {
        public long toNanos(long d)   { return x(d, C1/C0, MAX/(C1/C0)); }
        public long toMicros(long d)  { return d; }
        public long toMillis(long d)  { return d/(C2/C1); }
        public long toSeconds(long d) { return d/(C3/C1); }
        public long toMinutes(long d) { return d/(C4/C1); }
        public long toHours(long d)   { return d/(C5/C1); }
        public long toDays(long d)    { return d/(C6/C1); }
        public long convert(long d, TimeUnit u) { return u.toMicros(d); }
        int excessNanos(long d, long m) { return (int)((d*C1) - (m*C2)); }
    },

    // 毫秒转换工具
    MILLISECONDS {
        public long toNanos(long d)   { return x(d, C2/C0, MAX/(C2/C0)); }
        public long toMicros(long d)  { return x(d, C2/C1, MAX/(C2/C1)); }
        public long toMillis(long d)  { return d; }
        public long toSeconds(long d) { return d/(C3/C2); }
        public long toMinutes(long d) { return d/(C4/C2); }
        public long toHours(long d)   { return d/(C5/C2); }
        public long toDays(long d)    { return d/(C6/C2); }
        public long convert(long d, TimeUnit u) { return u.toMillis(d); }
        int excessNanos(long d, long m) { return 0; }
    },

    // 秒转换工具
    SECONDS {
        public long toNanos(long d)   { return x(d, C3/C0, MAX/(C3/C0)); }
        public long toMicros(long d)  { return x(d, C3/C1, MAX/(C3/C1)); }
        public long toMillis(long d)  { return x(d, C3/C2, MAX/(C3/C2)); }
        public long toSeconds(long d) { return d; }
        public long toMinutes(long d) { return d/(C4/C3); }
        public long toHours(long d)   { return d/(C5/C3); }
        public long toDays(long d)    { return d/(C6/C3); }
        public long convert(long d, TimeUnit u) { return u.toSeconds(d); }
        int excessNanos(long d, long m) { return 0; }
    },

    // 分钟转换工具
    MINUTES {
        public long toNanos(long d)   { return x(d, C4/C0, MAX/(C4/C0)); }
        public long toMicros(long d)  { return x(d, C4/C1, MAX/(C4/C1)); }
        public long toMillis(long d)  { return x(d, C4/C2, MAX/(C4/C2)); }
        public long toSeconds(long d) { return x(d, C4/C3, MAX/(C4/C3)); }
        public long toMinutes(long d) { return d; }
        public long toHours(long d)   { return d/(C5/C4); }
        public long toDays(long d)    { return d/(C6/C4); }
        public long convert(long d, TimeUnit u) { return u.toMinutes(d); }
        int excessNanos(long d, long m) { return 0; }
    },

    // 小时转换工具
    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, TimeUnit u) { return u.toHours(d); }
        int excessNanos(long d, long m) { return 0; }
    },

    // 天转换工具
    DAYS {
        public long toNanos(long d)   { return x(d, C6/C0, MAX/(C6/C0)); }
        public long toMicros(long d)  { return x(d, C6/C1, MAX/(C6/C1)); }
        public long toMillis(long d)  { return x(d, C6/C2, MAX/(C6/C2)); }
        public long toSeconds(long d) { return x(d, C6/C3, MAX/(C6/C3)); }
        public long toMinutes(long d) { return x(d, C6/C4, MAX/(C6/C4)); }
        public long toHours(long d)   { return x(d, C6/C5, MAX/(C6/C5)); }
        public long toDays(long d)    { return d; }
        public long convert(long d, TimeUnit u) { return u.toDays(d); }
        int excessNanos(long d, long m) { return 0; }
    };
    
    // 这几个常量是时间转换的单位大小
    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;

    // 这个方法具体是什么意思,我不管了,反正是个TimeUnit类的内部使用而已
    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;
    }

    // 此处没有给出其它成员方法,不急,稍后介绍
}

具体怎么用呢?我们举个例子(2天换算成小时,再把48小时换算成天):

// 把2天换算成小时,有两种写法
long hours = TimeUnit.DAYS.toHours(2);
long hours2 = TimeUnit.HOURS.convert(2, TimeUnit.DAYS);
// 把48小时换算成天,有两种写法
long days = TimeUnit.HOURS.toDays(48);
long days2 = TimeUnit.DAYS.convert(48, TimeUnit.HOURS);

2、其它的操作方法

2.1、timedWait方法

作用:调用obj的wait()方法,让当前线程阻塞,阻塞的最长时间为timeout,超过了这个时间,该线程自动被唤醒。

第一个问题,timeout没有指定时间单位,我们怎么知道它代表多长时间呢?

是这样的,比如,TimeUnit.SECONDS.timedWait(obj,2.23441)代表2.23441秒,                 

                                TimeUnit.MILLISECONDS.timedWait(obj,2.23441)代表2.23441毫秒;

第二个问题,wait(ms, ns);ms是毫秒数,ns是纳秒数,为什么要这么写呢?

因为大部分CPU是做不到纳秒级的,都是毫秒就OK,但是我们有时没有办法让时间精度只精确到毫秒,比如就输入一个2.5657346464757575毫秒,你咋办,所以就保证毫秒的精度,对于后面更加细致的时间,直接四舍五入。

    public void timedWait(Object obj, long timeout)
            throws InterruptedException {
        if (timeout > 0) {
            long ms = toMillis(timeout);
            int ns = excessNanos(timeout, ms);
            obj.wait(ms, ns);
        }
    }

2.2、timedJoin方法

作用:让thread调用join()方法,放弃当前CPU的使用权(意味着等待),要放弃timeout这么久,等过了这个时间,thread再去竞争CPU的使用权接着运行。timeout的时间单位同上。

和直接调用某个线程的join(long ms, long ns) 方法没什么区别。

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

2.3、sleep方法

作用:让当前线程睡眠timeout这么长的时间。timeout的单位同上。

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

2.4、int excessNanos(long d, long m) 方法

excessNanos(long d, long m) 是供上面3个方法使用的,参数d是表示一段时间,具体是什么时间,要看调用上面3个方法的时间单位是哪个,比如 TimeUnit.HOURS.sleep(1.5).中1.5就表示1.5个小时,因此excessNanos(long d, long m)方法中的d此时也就表示小时。 参数m表示毫秒数。

上面这段可能讲得不好,举个例子就明白了,比如  time = 2.123456789秒,此时time里的毫秒就应该是m = 2.123,然后调用excessNanos(time, m) = ns,这里的ns = 456789 纳秒,意思就是将时间d分为 毫秒 + 纳秒,m为毫秒,返回的值为纳秒。

 

总结:上面3个方法都是对线程方面的wait、join、sleep方法进行了一层封装,可读性更好,因为用原始方法的话,需要我们自己去换算时间,比如sleep(2300),睡眠2.3秒,这都是比较简单的了(如果更加复杂了),要先将2.3秒换算成毫秒,其次读代码的时候,还要再次换算成秒,我们才能直接观地知道睡眠多久,可读性不好。但是如果使用TimeUnit工具类的话,可读性更好,不用我们去换算时间了,比如TimeUnit.SCONDS.sleep(2.3);睡眠2.3秒,代码可读性更好,还不用换算。

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值