JUC TimeUnit深入

2021-03-15  本文已影响0人  小王_min

TimeUnit是什么?

JUC的一部分,表示给定粒度单位的持续时间,并提供实用方法以跨单位进行转换,并在这些单位中执行计时和延迟操作。

包含的时间单位

时间单位之间的转化

包含的方法

  1. public long convert(long sourceDuration, TimeUnit sourceUnit)
    convert源码

这边的方法在每个枚举中都有相应的实现,最终会将传入的时间转换成方法调用的单位。
例如TimeUnit.SECONDS.convert(1, TimeUnit.HOURS),此方法就是将「1小时」转为以秒为单位,所以结果为3600

  1. public long toNanos(long duration)
    toNanos源码

此方法是将duration转为以纳秒为单位的数值。
例如TimeUnit.MICROSECONDS.toNanos(1),将1微秒转为纳秒为单位,所以结果为1000

  1. public long toMicros(long duration)
    toMicros源码

此方法是将duration转为以微秒为单位的数值。
例如TimeUnit.MILLISECONDS.toMicros(1),将1毫秒转为微秒为单位,所以结果为1000

  1. public long toMillis(long duration)
    toMillis源码

此方法是将duration转为以毫秒为单位的数值。
例如TimeUnit.SECONDS.toMillis(1),将1秒转为微秒为单位,所以结果为1000

  1. public long toSeconds(long duration)
    toSeconds源码

此方法是将duration转为以秒为单位的数值。
例如TimeUnit.MINUTES.toSeconds(1),将1分钟转为秒为单位,所以结果为60

  1. public long toMinutes(long duration)
    toMinutes源码

此方法是将duration转为以分钟为单位的数值。
例如TimeUnit.HOURS.toMinutes(1),将1小时转为分钟为单位,所以结果为60

  1. public long toHours(long duration
    toHours源码

此方法是将duration转为以小时为单位的数值。
例如TimeUnit.DAYS.toHours(1),将1天转为小时为单位,所以结果为24

  1. public long toDays(long duration)
    toDays源码

此方法是将duration转为以天为单位的数值。
例如TimeUnit.HOURS.toDays(48),将48小时转为天为单位,所以结果为2

  1. abstract int excessNanos(long d, long m)
    excessNanos源码

取得时间量(单位取决于调用方)的纳秒数
使用场景:TimeUnit#timedWait

  1. public void timedWait(Object obj, long timeout)
    timedWait源码

timedWait原理(本质上就是Object.wait()):

  1. 获取毫秒数
  2. 获取纳秒数
  3. obj.wait()


    wait源码
    wait源码

等待阻塞时底层调用的是Object.wait,而这个wait的超时时间最小支持ns级。所以在调用的时候取得纳秒数,如果999999>纳秒数>0,那么就多等待1ms。

  1. public void timedJoin(Thread thread, long timeout)
    timedJoin源码

同理timedWait,同样是调用Thread.join(),同样最小支持ns级

join源码
  1. public void sleep(long timeout)
    sleep源码

同理timedWait,同样是调用Thread.join(),同样最小支持ns级

sleep源码

为啥TimeUnit要对sleepwait额外封装呢?

首先来看看如何使用?

public class Demo {
    public static void main(String[] args) throws InterruptedException {
        new Thread(() -> {
            // do something

            try {
                // 1. 使用TimeUnit睡眠2s
                TimeUnit.SECONDS.sleep(2);
                // 2. 使用Thread.sleep()
                Thread.sleep(2 * 1000);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }).start();
    }
}

从以上的代码可以很明显地看出,使用TimeUnit的方式会更加的简洁且语义明确。

使用的场景

  1. 所有需要对时间进行单位之间的转化action或者是有使用时间的场景,例如:reentrantLock.tryLock(1, TimeUnit.SECONDS);
  2. sleep()wait()join()相关的操作,使用TimeUnit的封装方法可使得程序更加可读。
上一篇下一篇

猜你喜欢

热点阅读