TimeUnit是什么?
JUC的一部分,表示给定粒度单位的持续时间,并提供实用方法以跨单位进行转换,并在这些单位中执行计时和延迟操作。
包含的时间单位
- NANOSECONDS:纳秒
- MICROSECONDS:微秒
- MILLISECONDS:毫秒
- SECONDS:秒
- MINUTES:分
- HOURS:时
- DAYS:天
时间单位之间的转化
- 1000 * NANOSECONDS(纳秒) = 1 * MICROSECONDS(微秒)
- 1000 * MICROSECONDS(微秒) = 1 * MILLISECONDS(毫秒)
- 1000 * MILLISECONDS(毫秒) = 1 * SECONDS(秒)
- 60 * SECONDS(秒) = 1 * MINUTES(分)
- 60 * MINUTES(分) = 1 * HOURS(时)
- 24 * HOURS(时) = 1 * DAYS(天)
包含的方法
-
public long convert(long sourceDuration, TimeUnit sourceUnit)
convert源码
- sourceDuration:指的是需要转化的时间量
- sourceUnit:指的是需要转化的时间单位
这边的方法在每个枚举中都有相应的实现,最终会将传入的时间转换成方法调用的单位。
例如TimeUnit.SECONDS.convert(1, TimeUnit.HOURS)
,此方法就是将「1小时」转为以秒为单位,所以结果为3600
。
-
public long toNanos(long duration)
toNanos源码
- duration:指的是时间量(单位取决于调用方)
此方法是将duration转为以纳秒为单位的数值。
例如TimeUnit.MICROSECONDS.toNanos(1)
,将1微秒转为纳秒为单位,所以结果为1000
。
-
public long toMicros(long duration)
toMicros源码
- duration:指的是时间量(单位取决于调用方)
此方法是将duration转为以微秒为单位的数值。
例如TimeUnit.MILLISECONDS.toMicros(1)
,将1毫秒转为微秒为单位,所以结果为1000
。
-
public long toMillis(long duration)
toMillis源码
- duration:指的是时间量(单位取决于调用方)
此方法是将duration转为以毫秒为单位的数值。
例如TimeUnit.SECONDS.toMillis(1)
,将1秒转为微秒为单位,所以结果为1000
。
-
public long toSeconds(long duration)
toSeconds源码
- duration:指的是时间量(单位取决于调用方)
此方法是将duration转为以秒为单位的数值。
例如TimeUnit.MINUTES.toSeconds(1)
,将1分钟转为秒为单位,所以结果为60
。
-
public long toMinutes(long duration)
toMinutes源码
- duration:指的是时间量(单位取决于调用方)
此方法是将duration转为以分钟为单位的数值。
例如TimeUnit.HOURS.toMinutes(1)
,将1小时转为分钟为单位,所以结果为60
。
-
public long toHours(long duration
toHours源码
- duration:指的是时间量(单位取决于调用方)
此方法是将duration转为以小时为单位的数值。
例如TimeUnit.DAYS.toHours(1)
,将1天转为小时为单位,所以结果为24
。
-
public long toDays(long duration)
toDays源码
- duration:指的是时间量(单位取决于调用方)
此方法是将duration转为以天为单位的数值。
例如TimeUnit.HOURS.toDays(48)
,将48小时转为天为单位,所以结果为2
。
-
abstract int excessNanos(long d, long m)
excessNanos源码
- d:指的是时间量(单位取决于调用方)
- m:指的是毫秒数
取得时间量(单位取决于调用方)的纳秒数
使用场景:TimeUnit#timedWait
等
-
public void timedWait(Object obj, long timeout)
timedWait源码
- obj:要超时等待的对象
- timeout:超时时间
timedWait
原理(本质上就是Object.wait()):
- 获取毫秒数
- 获取纳秒数
-
obj.wait()
wait源码
wait源码
等待阻塞时底层调用的是
Object.wait
,而这个wait的超时时间最小支持ns级。所以在调用的时候取得纳秒数,如果999999>纳秒数>0,那么就多等待1ms。
-
public void timedJoin(Thread thread, long timeout)
timedJoin源码
- thread:需要join的线程
- timeout:超时时间
同理
timedWait
,同样是调用Thread.join()
,同样最小支持ns级
-
public void sleep(long timeout)
sleep源码
- timeout:超时时间
同理
timedWait
,同样是调用Thread.join()
,同样最小支持ns级
为啥TimeUnit要对sleep
和wait
额外封装呢?
首先来看看如何使用?
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的方式会更加的简洁且语义明确。
使用的场景
- 所有需要对时间进行单位之间的转化action或者是有使用时间的场景,例如:
reentrantLock.tryLock(1, TimeUnit.SECONDS);
。 -
sleep()
、wait()
、join()
相关的操作,使用TimeUnit的封装方法可使得程序更加可读。