如何生成随机数

这篇博客探讨了Java中Random类在多线程环境下可能出现的相同随机数问题,以及如何通过ThreadLocalRandom解决这个问题。ThreadLocalRandom利用每个线程的独立seed避免了冲突,提高了性能。示例代码展示了正确使用ThreadLocalRandom的方式,强调每个线程应独立调用current()方法获取随机数生成器。
摘要由CSDN通过智能技术生成

我们都知道,JDK 自带一个 Random 类,可以 生成随机数。但是 ,这个类有个问题,多线程情况下,可能产生相同的随机数。代码如下:

 protected int next(int bits) {
        long oldseed, nextseed;
 // 多线程时,使用了相同的 seed,那么就会产生相同的随机数
        AtomicLong seed = this.seed; 
        do {
            oldseed = seed.get();
            nextseed = (oldseed * multiplier + addend) & mask;

                  // 这里,多线程,当seed相同时,只会有一个 线程更新成功
                  // 其他线程 更新失败会,会再次去生成一个随机数
                  // 直到成功为止, cas自旋 虽然解决了问题,但 会消耗cpu资源,性能也底下
        } while (!seed.compareAndSet(oldseed, nextseed)); 
        return (int)(nextseed >>> (48 - bits));
    }

于是,有一个新的类 ThreadLocalRandom

public static ThreadLocalRandom current() {
        if (UNSAFE.getInt(Thread.currentThread(), PROBE) == 0)
            localInit(); // 给当前线程 生成自己的 seed
        return instance;
    } 

// 使用当前线程的 seed,获取新的 seed
final long nextSeed() {
        Thread t; long r; // read and update per-thread seed
        UNSAFE.putLong(t = Thread.currentThread(), SEED,
                       r = UNSAFE.getLong(t, SEED) + GAMMA);
        return r;
    }


//实例代码
/**

这段代码好像不对啊,根据上面的 源码来看,这里生成的每个 线程 用的 seed 都是 主线程的啊
另外 ThreadLocalRandom  是单例的,current() 永远只能获取到一个 实例对象

*/
Random random = ThreadLocalRandom.current();
        for (int i = 0; i < 5; ++i) {
            new Thread(() -> {
                System.out.println(Thread.currentThread() + " "+random.nextInt(5));
            }).start();
        }


/**
正确使用 ThreadLocalRandom 
*/
for (int i = 0; i < 5; ++i) {
            new Thread(() -> {
                // 每个线程 自己去 调用 current() 来获取 ThreadLocalRandom 才对
                Random random = ThreadLocalRandom.current();
                System.out.println(Thread.currentThread() + " "+random.nextInt(5));
            }).start();
        }

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值