每天一个java类之Random
2014-04-28 20:02
351 查看
其实没法做到每天一个啦,就几天一个好了
主要是因为面试时,经常被问到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));
}
主要是因为面试时,经常被问到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入门#每天一个小程序#全排列
- java练习题,每天一个java小程序-1…
- [每天一个知识点]18-Java语言-在switch中接受String类型
- 1.每天一个java小程序之猜数字游戏
- 每天一个java小程序之数组复制与合并
- java练习题,每天一个java小程序-1…
- [每天一个知识点]6-Java语言-char和code point
- 每天一个java练习之数组常用操作(1)
- 每天一个Java类之AtomicLong
- java练习题,每天一个java小程序-9
- java练习题,每天一个java小程序-1…
- 每天一个数据结构——三种简单排序算法及Java实现
- 2.每天一个java小程序之输入输出的两种方式
- java练习题,每天一个java小程序-1…
- 一个线程安全的计数器实现(java),可以让一个变量每天从1开始递增
- 用java中的Math.random()函数产生一个简单的随机字符串
- Java用Math.random()生成一个50-100间的整型随机数
- java练习题,每天一个java小程序-1…
- 每天一个数据结构——快速排序及Java实现
- java练习题,每天一个java小程序-9