前言
Java程序中,我们时常会有需要使用到计时的需求,比如统计某一段程序运行时间,以此判断程序的效率,又例如统计用户操作的时间等等。因此,掌握好java计时功能的使用,非常关键,是每一个java开发者必学的内容。
新手常见的误区Sleep()
对很多初学java的新手来说,最简单的方法可能是使用Thread类中的自带方法sleep(int ms),单位为毫秒。
因其操作简单,只需要一个方法即可解决,需要计时多少毫秒就设定sleep()的参数。但是,使用sleep()有着诸多问题。
第一,它本身是一个线程的休眠方法,休眠也就意味着这个线程被暂时阻塞,无法工作;
第二,由于线程被休眠阻塞到重新执行的过程中需要经过算法调度,因此,实际等待的时间通常会略长于设定的毫秒数,这就导致计时的精度受到影响。
三种计时方法
1.使用System类中的currentTimeMillis()方法
这种应该是大家接触比较多的一个方法,学习Java se部分基本都会涉及到。
获取19701月1日0时0分0秒至今的毫秒数,于是我们可以这样获取经过的时间。
long millis1 = System.currentTimeMillis();
//do something
long millis2 = System.currentTimeMillis();
long time=millis2-millis1;//经过的毫秒数
2.使用System类中的nanoTime()方法
这个方法的返回值为纳秒(nanosecond),它的计算和cpu的时钟周期有关,因此精度相对currentTimeMillis()更高,但是执行一次的耗时也会更高。返回值与系统的时间无关,甚至可能是负数,只能用来计算两次,求经过的时间。
long millis1 = System.nanoTime();
//do something
long millis2 = System.nanoTime();
long time=millis2-millis1;//经过的毫秒数
3.使用StopWatch类
StopWatch是位于org.springframework.util包下的一个工具类,通过它可方便的对程序部分代码进行计时(ms级别),适用于同步单线程代码块。相对于前两种,在查看代码计时的时候更加方便。下面是一个简单的例子。
StopWatch sw = new StopWatch("test");
sw.start("task1");
// do something
Thread.sleep(160);
sw.stop();
sw.start("task2");
// do something
Thread.sleep(240);
sw.stop();
System.out.println("sw.prettyPrint()输出:");
System.out.println(sw.prettyPrint());
关于计时的一些总结
三种方法中,首推的是第三种,因为前两种虽然写起来更轻松,却相对不好管理,在实际开发中,代码量大的时候,更容易混淆自己的思路。当然也是可以使用的。
对于计时,其实无论是哪种方法,都无法避免误差,实际精度也难免受限于硬件。不过对于大多数的使用上,毫秒级的精度对我们已经足够了。