Java系统时钟几个值得思考的问题
Java系统时钟几个值得思考的问题
BlackJoker 发表于2年前
Java系统时钟几个值得思考的问题
  • 发表于 2年前
  • 阅读 7
  • 收藏 0
  • 点赞 0
  • 评论 0

新睿云服务器60天免费使用,快来体验!>>>   

System.currentTimeMillis()是依赖于系统时钟的,也就是说,如果你把自己的系统时钟更改了,这个函数的返回会立即生效,变成更改后的值;

System.nanoTime()主要用于记录一个时间段的长度,或者说一个超时,在这个过程中,你更改系统时钟也不会影响。

两个方法的精度一个是毫秒,一个是纳秒,但都是不靠普的(有些系统的时间粒度是10ms),nanoTime()的调用也会消耗几微妙,所以不靠普;

但粒度不是我讨论的重点。

 

我们程序中的timer是很常用的功能,归根到底到下面的API:

 

LockSupport. public static void parkNanos(long nanos)

 和

 

 

Thread.sleep(long millis)

 

 

不幸的是,但它们都是基于系统时钟的。

下面是我的测试,这个测试的过程是:启动后等待10秒钟,然后打印等待的时间:

public static void main(String[] args) throws InterruptedException {
		long s = System.nanoTime();
		int _10sec = 10 * 1000;
		LockSupport.parkNanos(TimeUnit.MILLISECONDS.toNanos(_10sec));
		long e = System.nanoTime();
		long used = e - s;
		System.out.println("Used:" + TimeUnit.NANOSECONDS.toMillis(used));
	}

 在运行上面程序之后,在系统命令行执行下面命令重置时间:

[atlas@atlas-pc ~]$ date && sudo date -s 16:10:40
2013年 04月 10日 星期三 16:10:57 CST
2013年 04月 10日 星期三 16:10:40 CST

 java程序输出:Used:27889

我把时钟向前拨了17s,一个park10s的程序27秒后才结束;

同样的,测试Thread:

public static void main(String[] args) throws InterruptedException {
		long s = System.nanoTime();
		int _10sec = 10 * 1000;
		Thread.sleep(_10sec);
		long e = System.nanoTime();
		long used = e - s;
		System.out.println("Used:" + TimeUnit.NANOSECONDS.toMillis(used));
	}

 运行后,重置时钟:

[atlas@atlas-pc ~]$ date && sudo date -s 16:33:40
2013年 04月 10日 星期三 16:34:03 CST
2013年 04月 10日 星期三 16:33:40 CST

 

java程序输出:Used:33569

 

这篇文章介绍了系统时钟和Java里面的几个API。

 

结论:

当我们重置服务器的时间(有些是通过网络同步的),

1,那些依赖系统时钟的程序(timer,scheduler,etc)会出现问题,

2,依赖时间判断的心跳会出问题,

 

UPDATE:

经过后期的测试,发现只有在linux下有上面的问题,MAC和windows都没有。

后面我做了一个sleep程序,调用系统的sleep 命令,然后Porcess.waitFor(),可以避免时间往前拨的问题。 可以用于一些非常关键的Java Timer的调度。  

 

 

标签: java 时钟 scheduler
  • 打赏
  • 点赞
  • 收藏
  • 分享
共有 人打赏支持
粉丝 1
博文 17
码字总数 9270
×
BlackJoker
如果觉得我的文章对您有用,请随意打赏。您的支持将鼓励我继续创作!
* 金额(元)
¥1 ¥5 ¥10 ¥20 其他金额
打赏人
留言
* 支付类型
微信扫码支付
打赏金额:
已支付成功
打赏金额: