当前位置:   article > 正文

Java源码之Random_java.random nextint函数源码

java.random nextint函数源码

import java.util.Random;


即util包下有Random类,其包含了很多常用方法
常用的有
nextDouble() ===> 返回[0,1)之间的随机数(double类型)
nextFloat() ===> 返回[0,1)之间的随机数(float类型)
nextInt(n) ===> 返回[0,n)之间的整数
这些方法都不是静态的!!,所以得先创建Random对象再使用

值得注意的是,经常使用的"double x = Math.random()",其实它的实现也是调用Random来实现的
源码:

RandomNumberGeneratorHolder:



故Math.random()的实现就是调用Random类的nextDouble()方法实现的

所以一个自然而然的问题是,哪种方式更快?为什么?
① 最“无脑”给出的答案是使用Random类来实现,因为少了一层调用
② 注意到,Math类是在java.lang包下的,是默认装载到JVM上的,并且
Math类中RandomNumberGeneratorHolder类和randomNumberGenerator方法都是
static final类型的(好像static final也是先装载?),使用这样的预装载类型会不会更快些?
③ 既然Math.random的实现如上,则Math类定义中必然已经导入了Random类,查看源码果然是
所以,如果从预装载会更快些这个角度看,直接使用Random还是会更快一些:大家都预装载了,我比你少一层调用
唯一一点点疑问是:是不是java默认导入的包java.lang中的类所依赖的类也默认装载了?

不是,JVM肯定没有将Random视为默认装载的类,证据就是单独用Random时还要单独导入包


一个比较靠谱的机制应该是,默认的包应该(也应当)是一个“闭环”,不然默认导入这个含义就没意义了

猜测是,默认还是导入那些(java.lang等),如果没有使用“外包”,则不导入。。。

(有空还是研究一下JVM编译装载的顺序。。。还有默认的包的类装载是不是有什么特殊的地方)
④ 先看结果,实验一波,两种方法产生10000个随机数(nextDouble()),看哪个快
 

Math.random:0.154s

Random random ===> random.nextDouble:0.132s

为防止误差,多运行了几次,发觉波动很大。。。

换做100万次,都是7s多一点。。。

回到测试代码:

问题①:start要放在Random random前面

===>结果一样。。

所以虚拟机装载的时间应该和run时候没关系,import导入的包在方法运行之前就装载了

随之而来的问题是,这个时间测试代码根本没法测试。。

还有一点,就算是执行到Math.random或者Random random才装载,多次运行时,JVM应该都是使用第一次装载过的class(很显然的推测:JVM会将最近使用的class保留)

所以代码的测试时间其实只是执行100万次运行已经装载好的nextDouble() + 输出语句的时间,故没啥区别。

 

PS:一个有趣的现象:

System.out那一句其实是猜测,注释掉了以后发现竟然真的被优化了,多次运行时间基本稳定在0.024s(不注释是7s+),为了验证,将for注释掉只运行一次,结果?

并不是0.024s,哈哈哈

有时就是0秒(currentTimeMillis本身只能精确到ms),猜测应该是for语句本身的开销(语句本身,变量i等等等)

为了验证,将代码改为:

本想以一个break来确保执行一次,确得到还是得到单独运行一次的时间,难道说编译器真的这么厉害?能判断出加break后其实只执行一次从而不管for了??

觉得不太可能,觉得0.024s应该不仅仅是for循环的开销,用break的代码应该也是有for开销的,验证:

只循环一次,结果还是0s,基本确定了,0.024s应该不是for的开销,可能是实际运行中编译器优化所花费的时间。

声明:本文内容由网友自发贡献,不代表【wpsshop博客】立场,版权归原作者所有,本站不承担相应法律责任。如您发现有侵权的内容,请联系我们。转载请注明出处:https://www.wpsshop.cn/w/很楠不爱3/article/detail/605368
推荐阅读
相关标签
  

闽ICP备14008679号