java中Random实现原理
Random使⽤
java中使⽤Random类来产⽣随机数。
import java.util.Random;
public class Client {
public static void main(String[] args) {
test();
test();
}
private static void test() {
Random random = new Random(10000);
for (int i = 0; i < 5; i++) {
System.out.Int(10000) + " ");
}
System.out.println();
}
}
输出结果为
2208 572 9116 3475 4500
2208 572 9116 3475 4500
只要种⼦相同,产⽣的随机数序列就是相同的,所以说Random是⼀种伪随机数的实现。
Random原理
/
**
* 随机数种⼦
*/
private final AtomicLong seed;
/**
* ⽆参构造器,使⽤当前时间纳秒值
*/
public Random() {
this(seedUniquifier() ^ System.nanoTime());
}
private static long seedUniquifier() {
/
/ L'Ecuyer, "Tables of Linear Congruential Generators of
// Different Sizes and Good Lattice Structure", 1999
for (;;) {
long current = ();
long next = current * 1181783497276652981L;
if (seedUniquifierpareAndSet(current, next))
return next;
}
}
⽆参构造器使⽤当前时间当做创建种⼦的⼀部分,可以看做每次都是不同的。
/**
* 获取随机数
*/
protected int next(int bits) {
long oldseed, nextseed;
AtomicLong seed = this.seed;
do {
oldseed = ();
nextseed = (oldseed * multiplier + addend) & mask;
} while (!seedpareAndSet(oldseed, nextseed));
return (int)(nextseed >>> (48 - bits));
}
通过⼀个固定算法,使⽤CAS将⼀个旧的种⼦更新为新种⼦。
ThreadLocalRandom
Random获取随机数使⽤CAS更新种⼦,在⾼并发环境下会⼤量⾃旋重试,性能下降,这种情况下可以使⽤ThreadLocalRandom。import urrent.ThreadLocalRandom;
public class Client2 {
public static void main(String[] args) {
ThreadLocalRandom threadLocalRandom = ThreadLocalRandom.current();
for (int i = 0; i < 5; i++) {
System.out.Int(100) + " ");
}
}
}
输出为
73 78 0 68 12
通过⼀个静态⽅法创建,不能⾃⼰设置种⼦。
public class ThreadLocalRandom extends Random {
// 可以直接操作内存的⼯具类
private static final Unsafe U = Unsafe();
// 种⼦
private static final long SEED = U.objectFieldOffset
(Thread.class, "threadLocalRandomSeed");
private static final long PROBE = U.objectFieldOffset
(Thread.class, "threadLocalRandomProbe");
/
** 单例 */
static final ThreadLocalRandom instance = new ThreadLocalRandom();
/**
* 获取单例对象
*/
public static ThreadLocalRandom current() {
if (U.getInt(Thread.currentThread(), PROBE) == 0)
localInit();
return instance;
}
}
使⽤饿汉式的单例模式来创建ThreadLocalRandom对象
/**
* Returns a pseudorandom {@code int} value.
*
* @return a pseudorandom {@code int} value
*/
public int nextInt() {
return mix32(nextSeed());
}
final long nextSeed() {
Thread t; long r; // read and update per-thread seed
U.putLong(t = Thread.currentThread(), SEED,
r = U.getLong(t, SEED) + GAMMA);
return r;
}
ThreadLocalRandom每个线程保存⼀份种⼦,每次更新⾃⼰线程的种⼦,避免⾼并发下的竞争。
/** The current seed for a ThreadLocalRandom */
@jdk.internal.vm.annotation.Contended("tlr")
long threadLocalRandomSeed;
/** Probe hash value; nonzero if threadLocalRandomSeed initialized */
@jdk.internal.vm.annotation.Contended("tlr")
int threadLocalRandomProbe;
种⼦保存在Thread类下threadLocalRandomSeed和threadLocalRandomProbe字段,原理类似于ThreadLocal,⽤空间换时间。SecureRandom
import java.security.SecureRandom;
public class Client3 {
public static void main(String[] args) {
SecureRandom secureRandom = new SecureRandom();
System.out.Algorithm());
for (int i = 0; i < 5; i++) {
System.out.Int(100) + " ");
}java生成随机数的方法
}
}
输出为
DRBG
7 23 20 92 31
SecureRandom是⼀个强随机数⽣成器,会收集计算机的各种信息,使⽤加密算法创建随机数。windows下默认使⽤DRBG算法。参考
版权声明:本站内容均来自互联网,仅供演示用,请勿用于商业和其他非法用途。如果侵犯了您的权益请与我们联系QQ:729038198,我们将在24小时内删除。
发表评论