TimeUnit 深入源码解析

  TimeUnit是JUC包下提供的一个枚举类,表示给定单元粒度的时间段。

  演示示例:

  首先,我们先看一个示例,示例中包含了TimeUnit的所有功能。

package com.securitit.serialize.juc;

import java.util.Date;
import java.util.concurrent.TimeUnit;

import org.assertj.core.util.DateUtil;

public class TimeUnitTester {

	public static void main(String[] args) throws Exception {
		// 使用TimeUnit的HOURS时间粒度.将24小时转换为天.
		System.out.println(TimeUnit.HOURS.toDays(24));
		// 使用TimeUnit的DAYS时间粒度.将1天转换为小时.
		System.out.println(TimeUnit.DAYS.toHours(1));
		// Thread.sleep功能.
		System.out.println(Thread.currentThread().getName() + ".即将睡眠状态.");
		TimeUnit.SECONDS.sleep(1);
		System.out.println(Thread.currentThread().getName() + ".已过睡眠状态.");
		// Object.wait功能.
		final Object monitor = new Object();
		Thread t1 = new Thread(() -> {
			try {
				System.out.println(Thread.currentThread().getName() + ".即将进入超时阻塞状态.");
				synchronized (monitor) {
					TimeUnit.SECONDS.timedWait(monitor, 5);
				}
				System.out.println(Thread.currentThread().getName() + ".阻塞超时,恢复运行状态.");
			} catch (Exception ex) {
				ex.printStackTrace();
			}
		});
		t1.start();
		// Thread.join功能.
		TimeUnit.SECONDS.timedJoin(t1, 1);
		System.out.println(t1.getName() + ".线程集合超时.");
	}

}

  输出结果:

1
24
main.即将睡眠状态.
main.已过睡眠状态.
Thread-0.即将进入超时阻塞状态.
Thread-0.线程集合超时.
Thread-0.阻塞超时,恢复运行状态.

  从输出结果可以看出,TimeUnit针对时间做了处理,同时较通用的依赖时间的操作,也使用它独有的时间粒度进行了二次封装。

  源码分析:

  TimeUnit时间粒度:

  · NANOSECONDS - 纳秒

  · MICROSECONDS - 微秒

​  · MILLISECONDS - 毫秒

  · SECONDS - 秒

  · MINUTES - 分钟

  · HOURS - 小时

  · DAYS - 天

  TimeUnit API:

// 转纳秒.
public long toNanos(long d);
// 转微秒.
public long toMicros(long d);
// 转毫秒.
public long toMillis(long d);
// 转秒.
public long toSeconds(long d);
// 转分钟.
public long toMinutes(long d);
// 转小时.
public long toHours(long d);
// 转天.
public long toDays(long d);
// 通用转换.
public long convert(long d, TimeUnit u);
// 计算要等待的多余纳秒参数的实用程序.
int excessNanos(long d, long m);
// 针对Object.wait的二次封装.
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);
    }
}
// 针对Thrad.join的二次封装.
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);
    }
}
// 针对Thread.sleep的二次封装.
public void sleep(long timeout) throws InterruptedException {
    if (timeout > 0) {
        long ms = toMillis(timeout);
        int ns = excessNanos(timeout, ms);
        Thread.sleep(ms, ns);
    }
}

  API中,toNanos、toMicros、toMillis、toSeconds、toMinutes、toHours、toDays、convert、excessNanos几个API,每种时间粒度的计算方式存在差异,中心思想都是在计算时间,逻辑不是很复杂,可以自行查看。

  timedWait、timedJoin、sleep都是对已有功能的二次封装,使得在需要复杂时间限定时,使用起来更为方便。

  注:文中源码均来自于JDK1.8版本,不同版本间可能存在差异。

  如果有哪里有不明白或不清楚的内容,欢迎留言哦!

猜你喜欢

转载自blog.csdn.net/securitit/article/details/106984723