TimeUnit类详解

其类作者Doug Lea在其javadoc中写道:

A TimeUnit represents time durations at a given unit of granularity and provides utility methods to convert across units, and to perform timing and delay operations in these units. A TimeUnit does not maintain time information, but only helps organize and use time representations that may be maintained separately across various contexts. A nanosecond is defined as one thousandth of a microsecond, a microsecond as one thousandth of a millisecond, a millisecond as one thousandth of a second, a minute as sixty seconds, an hour as sixty minutes, and a day as twenty four hours.

解释:
TimeUnit表示给定粒度单位的持续时间,
常见的颗粒度有:
在这里插入图片描述

  • NANOSECONDS 纳秒
  • MICROSECONDS 微秒
  • MILLISECONDS 毫秒
  • SECONDS 秒
  • MINUTES 分
  • HOURS 时
  • DAYS 天

并提供跨单位转换以及在这些单位中执行计时和延迟操作的实用方法。时间单位不维护时间信息,只帮助组织和使用可以在不同上下文中单独维护的时间表示。纳秒定义为千分之一微秒,微秒定义为千分之一毫秒,毫秒定义为千分之一秒,分钟定义为六十秒,小时定义为六十分钟,一天定义为二十四小时。

其中以纳秒举例,如下:

在这里插入图片描述
方法中用的属性定义如下:
在这里插入图片描述

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); }	  // 转换成天
        // 例如,要将10分钟转换为纳秒,请使用:TimeUnit.NANOSECONDS.convert(10L, TimeUnit.MINUTES)
		// 参数:
		// d–给定源单元中的持续时间
		// u–d参数的单位(参数可以为如下类型:
		//				NANOSECONDS 纳秒、
		// 				MICROSECONDS 微秒、
		// 				MILLISECONDS 毫秒、
		// 				SECONDS 秒、
		// 				MINUTES 分、
		// 				HOURS 时、
		// 				DAYS 天)
		// 返回:
		// 此单位中转换的持续时间,如果转换将负溢出,则为Long.MIN_VALUE;如果转换将正溢出,则为Long.MAX_VALUE。
        public long convert(long d, TimeUnit u) {
    
     return u.toNanos(d); }
        // 用于计算等待、睡眠和加入的多余纳秒参数的实用程序。
		// 参数:
		// d–持续时间
		// m–毫秒数
		// 返回:
		// 纳秒数
        int excessNanos(long d, long m) {
    
     return (int)(d - (m*C2)); } 
    },

其中注意在使用convert方法的时候,将给定单位中的给定持续时间转换为此单位。从细粒度到粗粒度的转换会截断,因此会失去精度。例如,将999毫秒转换为秒将导致0。从粗粒度到细粒度的转换,参数在数值上会溢出,如果为负,则饱和为Long.MIN_VALUE;如果为正,则饱和为Long.MAX_VALUE。
同时上例中将10分钟转换为纳秒,也可以使用另外一种方法,在对应的枚举类对象中,直接调用转换方法,如下:

TimeUnit.MINUTES.toNanos( 10 );

对于excessNanos,其中颗粒度为纳秒、微秒对于该重写方法有具体的逻辑计算,颗粒度为毫秒、秒、分、时、天中该重写方法就都返回0了。
还有一个static long x(long d, long m, long over)方法如下:

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;
    }

该方法是用来检查从粗粒度到细粒度的转换,参数在数值上是否会溢出(参数在数值上会溢出,如果为负,则饱和为Long.MIN_VALUE;如果为正,则饱和为Long.MAX_VALUE),没有溢出就取正常值。
比如枚举对象MICROSECONDS对于toNanos的重写方法如下,该方法的作用是把微秒转为为纳秒,其方法内部就调用了x()进行检查是否溢出,如下:
在这里插入图片描述

当然TimeUnit类中还有枚举对象没用重写的方法,如下:

  • timedWait
    其内部还是调用了Object对象的wait()方法,只是转换为了对应的颗粒度,增加了可读性
  • timedJoin
    其内部还是调用了Thread对象的join()方法,只是转换为了对应的颗粒度,增加了可读性
  • sleep
    其内部还是调用了Thread类的sleep()方法,只是转换为了对应的颗粒度,增加了可读性

举例:

// 没有用TimeUnit类
public static void main(String[] args) {
    
    
 
        new Thread( new Runnable() {
    
    
 
            @Override
            public void run() {
    
    
                try {
    
    
                    Thread.sleep( 5 * 60 * 1000 );
                    System.out.println( "延时完成了");
                } catch (InterruptedException e) {
    
    
                    e.printStackTrace();
                }
            }
        }).start();  ;
    }

//用了TimeUnit类
public static void main(String[] args) {
    
    
 
        new Thread( new Runnable() {
    
    
 
            @Override
            public void run() {
    
    
                try {
    
    
                    TimeUnit.MINUTES.sleep( 5 );
                    System.out.println( "延时5分钟,完成了");
                } catch (InterruptedException e) {
    
    
                    e.printStackTrace();
                }
            }
        }).start();  ;
    }

可以看到延时五分钟的时候,有了TimeUnit类,我们不用再去进行时间的转换运算,Thread.sleep( 5 * 60 * 1000 );直接调用TimeUnit.MINUTES.sleep( 5 );即可,极大的增加了我们写代码的便捷性和可阅读性。


已完结
于2021.11.24 著
author:YuShiwen

猜你喜欢

转载自blog.csdn.net/MrYushiwen/article/details/121510165