其实没法做到每天一个啦,就几天一个好了
主要是因为面试时,经常被问到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));
}
美好的生命应该充满期待惊喜和感激