java

关注公众号 jb51net

关闭
首页 > 软件编程 > java > Java 并发ThreadlocalRandom

Java中并发下的ThreadlocalRandom的实现

作者:ZNineSun

本文介绍了Java1.8中的ThreadLocalRandom类,它在并发环境下比Random类有更好的性能,下面就来详细的介绍一下如何使用,感兴趣的可以了解一下

1. 背景

在看同事写的代码的时候发现代码里有很多像:

如果我们想要生成一个随机数,通常会使用Random类。但是在并发情况下Random生成随机数的性能并不是很理想,今天给大家介绍一下JUC包中的用于生成随机数的类–ThreadLocalRandom.(本文基于JDK1.8)

当然Random随机数也可以保证线程的安全,但是Random随机数生成是和种子seed有关,而为了保证线程安全性,Random通过CAS机制来保证线程安全性。

从next()方法中我们可以发现seed是通过自旋锁和CAS来进行修改值的。如果在高并发的场景下,那么可能会导致CAS不断失败,从而导致不断自旋,这样就可能会导致服务器CPU过高。我们可以看一下next的实现:

    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));
    }

2.为什么要用ThreadLocalRandom

ThreadLocalRandom是ThreadLocal和Random类的组合,它与当前线程隔离。因此,它通过简单地避免对Random对象的任何并发访问,在多线程环境中实现了更好的性能。

一个线程获得的随机数不受另一个线程的影响,而java.util.Random全局提供随机数。

此外,与Random 不同,ThreadLocalRandom不支持显式设置种子。相反,它会覆盖从Random继承的setSeed(long seed)方法,以便在调用时始终抛出UnsupportedOperationException。

现在让我们看一下生成随机int,long和double值的一些方法。

根据Oracle文档,我们只需要调用ThreadLocalRandom.current()方法,它将返回当前线程的ThreadLocalRandom实例。然后,我们可以通过调用类的可用实例方法来生成随机值。

int unboundedRandomValue = ThreadLocalRandom.current().nextInt());

上面的代码可以生成一个没有任何边界的随机int值

int boundedRandomValue = ThreadLocalRandom.current().nextInt(0, 100);

这是一个生成0到100之间的随机int值的示例,值得注意的是:包含下限0,不包含上限100

同样我们也可以与上面示例中所示类似的方式调用nextLong()和nextDouble()方法来生成long和double的随机值。

Java 8还添加了nextGaussian()方法来生成下一个正态分布的值,其值与生成器序列的值相差 0.0和1.0。

与Random类一样,我们也可以使用doubles(),ints()和longs()方法生成随机值流。

到此这篇关于Java中并发下的ThreadlocalRandom的文章就介绍到这了,更多相关Java 并发ThreadlocalRandom内容请搜索脚本之家以前的文章或继续浏览下面的相关文章希望大家以后多多支持脚本之家!

您可能感兴趣的文章:
阅读全文