java 不能用 random,关于Java中Random的一些使用细节

Random类相信大家都不陌生,但是必须掌握一些特定的细节才能在要求较高的场合用好该变量。这里分析一个多线程环境下Random的使用。

现在面临一个问题:有多个线程需要按照随机的方式取一个令牌,尽量让每个线程取得的令牌不一样,可以认为令牌就是一个数字,如1~100之内的一个整数。那么怎样实现能最好的解决这个问题呢?首先想到的是用一个同步的变量,使用一个

于是一位粗心的同学有了下面这样的接口:

public static int getRandomNumber(int scale)

{

Random random = new Random();

return random.nextInt(scale);

}

值得赞许的是,他没有直接在线程的run方法中直接使用代码,而是抽取出来作为一个接口公用,也许别处还能重用这份代码。但是在线程中使用时却发现,同一时刻,不同的线程获取到的伪随机数总是一样的,这与需求的要求不符。只有这么两行代码,函数也是可以重入的,问题出在哪里呢?

Random的实现是,在生成random实例的时候,会有一个伪随机种子,这个种子在实例创建的时候就生成了,也可以指定种子来创建实例。如果没有指定种子,则使用时间作为种子,时间的单位是纳秒,按道理来说两个时间完全撞在一起的概率也非常低了,但是实际上,在纳秒级别,时钟精度是有误差的,达不到这个精确度,因此会出现两个线程中的random实例使用了同一个种子,这样取第一个nextInt的时候也就是同一个值了。这也就是多个线程取得同一个值的原因。

那么对上述方法做一些改进,将其中的random修改为静态的成员变量可以解决该问题:

private static Random random = new Random();

public static int getRandomNumber(int scale)

{

return random.nextInt(scale);

}

这样应该就能够解决问题。但是运行时问题还是存在,还是有大量的相同的值。再看nextInt接口,是非线程安全的。加一个同步即可解决。

private static Random random = new Random();

public static int getRandomNumber(int scale)

{

synchronized (random)

{

return random.nextInt(scale);

}

}

其实这也是线程安全接口Math.random()的实现。

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值