java随机数语句_关于Java随机数

Java提供两种类型的随机数发生器

1.伪随机数发生器

伪随机数发生器采用特定的算法,将随机数种子seed转换成一系列的伪随机数。伪随机数依赖于seed的值,给定相同的seed值总是生成相同的随机数。伪随机数的生成过程只依赖CPU,不依赖任何外部设备,生成速度快,不会阻塞。

Java提供的伪随机数发生器有java.util.Random类和java.util.concurrent.ThreadLocalRandom类。

Random类采用AtomicLong实现,保证多线程的线程安全性,但正如该类注释上说明的,多线程并发获取随机数时性能较差。

多线程环境中可以使用ThreadLocalRandom作为随机数发生器,ThreadLocalRandom采用了线程局部变量来改善性能,这样就可以使用long而不是AtomicLong,此外,ThreadLocalRandom还进行了字节填充,以避免伪共享。

2.强随机数发生器

强随机数发生器依赖于操作系统底层提供的随机事件。强随机数生成器的初始化速度和生成速度都较慢,而且由于需要一定的熵累积才能生成足够强度的随机数,所以可能会造成阻塞。熵累积通常来源于多个随机事件源,如敲击键盘的时间间隔,移动鼠标的距离与间隔,特定中断的时间间隔等。所以,只有在需要生成加密性强的随机数据的时候才用它。

Java提供的强随机数发生器是java.security.SecureRandom类,该类也是一个线程安全类,使用synchronize方法保证线程安全,但jdk并没有做出承诺在将来改变SecureRandom的线程安全性。因此,同Random一样,在高并发的多线程环境中可能会有性能问题。

在linux的实现中,可以使用/dev/random和/dev/urandom作为随机事件源。由于/dev/random是堵塞的,在读取随机数的时候,当熵池值为空的时候会堵塞影响性能,尤其是系统大并发的生成随机数的时候,如果在随机数要求不高的情况下,可以去读取/dev/urandom来避免阻塞,方法是通过设置参数-Djava.security.egd=file:/dev/urandom

但这样由于jdk的一个bug,实际上需要这样指定这个值-Djava.security.egd=file:/dev/./urandom

原因是,在 sun.security.provider.SunEntries类,seedSource先读取系统参数java.security.egd,如果值为空的时候,读取java.security配置文件中的参数securerandom.source, 在通常情况下,就是读取参数securerandom.source,默认值是/dev/urandom。sun.security.provider.SeedGenerator

final static String URL_DEV_RANDOM = SunEntries.URL_DEV_RANDOM;

final static String URL_DEV_URANDOM = SunEntries.URL_DEV_URANDOM;

if (egdSource.equals(URL_DEV_RANDOM) || egdSource.equals(URL_DEV_URANDOM)) {

try {

instance = new NativeSeedGenerator();

if (debug != null) {

debug.println("Using operating system seed generator");

}

} catch (IOException e) {

if (debug != null) {

debug.println("Failed to use operating system seed "

+ "generator: " + e.toString());

}

}

} else if (egdSource.length() != 0) {

try {

instance = new URLSeedGenerator(egdSource);

if (debug != null) {

debug.println("Using URL seed generator reading from "

+ egdSource);

}

} catch (IOException e) {

if (debug != null)

debug.println("Failed to create seed generator with "

+ egdSource + ": " + e.toString());

}

}

在代码中可以看到当配置值是file:/dev/random或者file:/dev/urandom的时候,启用NativeSeedGenerator, 而在linux下的NativeSeedGenerator类的实现是这样的class NativeSeedGenerator extends SeedGenerator.URLSeedGenerator {

NativeSeedGenerator() throws IOException {

super();

}

}

而URLSeedGenerator的默认构造方法是URLSeedGenerator() throws IOException {

this(SeedGenerator.URL_DEV_RANDOM);

}

也就是说哪怕设置了-Djava.security.egd=file:/dev/urandom,最后的结果一样是读取file:/dev/random,解决办法就是使用linux的多种路径表示法,即使用file:/dev/./urandom来绕过这个问题。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值