每天一个java类之Random

其实没法做到每天一个啦,就几天一个好了

主要是因为面试时,经常被问到JVM源码,而我确实看的较少

那就补补吧。

今天是Random,去微软面试的时候,三面的面试官让写一个Random类,当然,有特殊要求的

恍惚间,我不记得Random怎么实现的,连怎么用的都模糊了。。。

Sigh~

Random

Java中的Random类生成的是伪随机数,使用的是48-bit的种子,然后调用一个linear congruential formula线性同余方程(Donald Knuth的编程艺术的3.2.1节)

如果两个Random实例使用相同的种子,并且调用同样的函数,那么生成的sequence是相同的

也可以调用Math.random()生成随机数

Random实例是线程安全的,但是并发使用Random实例会影响效率,可以考虑使用ThreadLocalRandom变量。

Random实例不是安全可靠的加密,可以使用java.security.SecureRandom来提供一个可靠的加密。

Random implements Serializable 可序列化的

AtomicLong seed 原子变量

long multiplier = 0x5DEECE66DL;

long addend = 0xBL;

long mask = (1L << 48) -1 ;

AtomicLong seedUniquifiler;

Random(){

this( seedUniquifier() ^ System.nanoTime() )

}

static long seedUniquifier(){

for(;;){

long current = seedUniquifier.get();

long next = current * 181783497276652981L;

if( seedUniquifier.compareAndSet(current,next))

return next;

}

}

// seed是随机生成器的初始值,由next()维护这个随机生成器

Random(long seed){

if(getClass() == Random.class)

this.seed = new AtomicLong(initialScramble(seed));

else{

this.seed = new AtomicLong();

setSeed(seed);

}

}

static long initialScramble(long seed){

return (seed ^ multiplier ) & mask;

}

重新设置seed, setSeed只使用48bit。并清空hasNextNextGussian标志

synchronize public void setSeed(long seed){

this.seed.set(initialScramble(seed));

hasNextNextGaussian = false;

}

生成下一个伪随机数,子类需要重写这个方法。

使用一个线性同余方程,生成伪随机数

protected int next(int bits){

long oldSeed,nextSeed;

AtomicLong seed = this.seed;

do {

oldSeed = seed.get();

nextSeed = (oldSeed * multiplier + addend) & mask;

}while( ! seed.compareAndSet(oldSeed,nextSeed) ) ;

return (int)(nextseed >>> (48-bits));

}

随机生成一个字节数组,并存放到用户传进来的bytes数组中。

public void nextBytes(byte[]bytes){

for(int i = 0 ,len = bytes.length; i < len ; ){

for(int rnd = nextInt(), n = Math.min(len-i,Integer.SIZE/Byte.SIZE); n- – >0; rnd >>= Byte.SIZE)

bytes[i++] = (byte) rnd;

}

}

要求2 ^ 32个证书生成的概率相等

int nextInt(){

return next(32);

}

生成一个伪随机数,等概率的一致分布0~n: [0-n)

要求n个数以等概率生成

该方法只给出一个approximately an unbiased source of independently chosen bits

对于2的幂次,给出一个corrent number of high-order bits from 伪随机生成器。

否则,返回一个correct number of low-order bits

int nextInt(int n){

if (n <= 0)

throw new IllegalArgumentException("n must be positive");

if ((n & -n ) == n) //n是2 的幂次

return (int ) ( (n * (long) next(31 )) >> 31 );

int bits,val;

do{

bits = next(31);

val = bits % n;

}while( bits – val + (n-1) < 0 );

return val;

}

public long nextLong(){

return ((long) (next(32)) << 32 ) + next(32);

}

boolean nextBoolean(){

return next(1) != 0;

}

float nextFloat(){

return next(24)/((float) (1 << 24));

}

美好的生命应该充满期待惊喜和感激

每天一个java类之Random

相关文章:

你感兴趣的文章:

标签云: