从零自学java消遣一下,看书有点脑阔疼,不如看看源码!(๑╹◡╹)ノ"""
JS中Math调用的都是本地方法,底层全是用C++写的,所以完全无法观察实现过程,Java的工具包虽然也有C/C++的介入,不过也有些是自己实现的。
本篇文章主要简单阐述Math.random()的实现过程。
Math隶属于java.lang包中,默认加载。本身是一个final类,方法都是静态方法,所以使用的时候不需要生成一个实例,直接调用Math.XX就行了。
一步一步观察该方法,首先是java.lang.Math:
public final class Math {
// 大量静态变量与方法
// ...
private static Random randomNumberGenerator;
private static synchronized void initRNG() {
if (randomNumberGenerator == null)
randomNumberGenerator = new Random();
}
public static double random() {
if (randomNumberGenerator == null) initRNG();
return randomNumberGenerator.nextDouble();
}
// ...other
}
这里面与random相关的操作有3个:
1、声明一个私有静态Random类randomNumberGenerator
2、若randomNumberGenerator未初始化,调用new Random()将其初始化
3、若randomNumberGenerator已经初始化,调用nextDouble方法并将其值返回
tips:synchronized关键字代表同步执行此方法,Java为多线程,所以为了保证randomNumberGenerator对象只被初始化一次,需要该关键字。比如两个线程同时调用了Math.random(),线程A发现rXX未被初始化,进入initRNG调用new Random()方法。此时线程B也发现了rXX未被初始化,但是initRNG是同步方法,所以挂起等待线程A执行完毕。当线程A执行完后把rXX初始化了,所以在initRNG中的if判断,线程B会直接返回。
所以简单来讲,random方法会在第一次调用时生成一个randomNumberGenerator对象,并调用其nextDouble方法生成随机数,之后的调用就只要持续调用此方法返回随机数就行了。
下面来看Random类是个什么鬼,来源于java.util.Random:
public class Random implements java.io.Serializable {
// 静态变量
/** use serialVersionUID from JDK 1.1 for interoperability */
static final long serialVersionUID = 3905348978240129619L;
private final AtomicLong seed;
private final static long multiplier = 0x5DEECE66DL;
pr